implementation Consistência de hashCode() em uma string Java




java how to hashcode (6)

O valor de hashCode de uma String Java é calculado como ( String.hashCode() ):

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

Há alguma circunstância (por exemplo, versão da JVM, fornecedor etc.) sob a qual a seguinte expressão será avaliada como falsa?

boolean expression = "This is a Java string".hashCode() == 586653468

Atualização # 1: Se você afirma que a resposta é "sim, existem tais circunstâncias" - então por favor, dê um exemplo concreto de quando "Esta é uma string Java" .hashCode ()! = 586653468. Tente ser tão específico / concreto que possível.

Atualização 2: Todos nós sabemos que depender dos detalhes de implementação do hashCode () é ruim em geral. No entanto, estou falando especificamente sobre String.hashCode () - então, por favor, mantenha a resposta focada em String.hashCode (). Object.hashCode () é totalmente irrelevante no contexto desta questão.


Eu encontrei algo sobre o JDK 1.0 e 1.1 e> = 1.2:

No JDK 1.0.xe 1.1.x, a função hashCode para strings longas funcionava por amostragem a cada enésimo caractere. Isso muito bem garantido você teria muitas seqüências de caracteres hashing para o mesmo valor, diminuindo assim a pesquisa de Hashtable. No JDK 1.2, a função foi aprimorada para multiplicar o resultado por 31 até então adicionar o próximo caractere em seqüência. Isso é um pouco mais lento, mas é muito melhor para evitar colisões. Fonte: http://mindprod.com/jgloss/hashcode.html

Algo diferente, porque você parece precisar de um número: Que tal usar o CRC32 ou MD5 em vez do hashcode e você está pronto - sem discussões e sem preocupações ...


Como dito acima, em geral você não deve confiar no código hash de uma classe que permaneça o mesmo. Observe que mesmo as execuções subseqüentes do mesmo aplicativo na mesma VM podem produzir diferentes valores de hash. AFAIK, a função hash da Sun JVM, calcula o mesmo hash em todas as execuções, mas isso não é garantido.

Note que isso não é teórico. A função hash para java.lang.String foi alterada no JDK1.2 (o hash antigo tinha problemas com strings hierárquicas como URLs ou nomes de arquivos, já que tendia a produzir o mesmo hash para strings que diferiam apenas no final).

java.lang.String é um caso especial, como o algoritmo de seu hashCode () é (agora) documentado, então você provavelmente pode confiar nisso. Eu ainda considero isso uma má prática. Se você precisar de um algoritmo hash com propriedades especiais e documentadas, basta escrever uma :-).


Outro problema (!) Com o qual se preocupar é a possível mudança de implementação entre versões adiantadas / tardias do Java. Eu não acredito que os detalhes da implementação estejam definidos e, portanto, potencialmente uma atualização para uma versão futura do Java possa causar problemas.

A linha inferior é, eu não confiaria na implementação do hashCode() .

Talvez você possa destacar qual problema você está realmente tentando resolver usando esse mecanismo, e isso irá destacar uma abordagem mais adequada.


Se você está preocupado com alterações e possivelmente com VMs incompatíveis, basta copiar a implementação do hashcode existente em sua própria classe de utilitário e usá-la para gerar seus hashcodes.


Você não deve confiar em um código hash igual a um valor específico. Só que ele retornará resultados consistentes dentro da mesma execução. Os documentos da API dizem o seguinte:

O contrato geral do hashCode é:

  • Sempre que é invocado no mesmo objeto mais de uma vez durante a execução de um aplicativo Java, o método hashCode deve retornar consistentemente o mesmo número inteiro, desde que nenhuma informação usada nas comparações de igual no objeto seja modificada. Esse inteiro não precisa permanecer consistente de uma execução de um aplicativo para outra execução do mesmo aplicativo.

EDIT Uma vez que o javadoc para String.hashCode () especifica como o código hash de String é calculado, qualquer violação disso violaria a especificação pública da API.


Eu posso ver essa documentação já em Java 1.2.

Embora seja verdade que, em geral, você não deve confiar em uma implementação de código hash que permaneça a mesma, agora é um comportamento documentado para java.lang.String , portanto, alterá-lo contaria como quebra de contratos existentes.

Sempre que possível, você não deve confiar em códigos hash que permaneçam iguais nas versões etc - mas em minha mente o java.lang.String é um caso especial simplesmente porque o algoritmo foi especificado ... contanto que você esteja disposto a abandonar compatibilidade com releases antes do algoritmo ser especificado, é claro.





hashcode