generate - java how to hashcode




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

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.


Apenas para responder sua pergunta e não continuar nenhuma discussão. A implementação do Apache Harmony JDK parece usar um algoritmo diferente, pelo menos parece totalmente diferente:

Sun JDK

public int hashCode() {
    int h = hash;
    if (h == 0) {
        int off = offset;
        char val[] = value;
        int len = count;

        for (int i = 0; i < len; i++) {
            h = 31*h + val[off++];
        }
        hash = h;
    }
    return h;
}

Apache Harmony

public int hashCode() {
    if (hashCode == 0) {
        int hash = 0, multiplier = 1;
        for (int i = offset + count - 1; i >= offset; i--) {
            hash += value[i] * multiplier;
            int shifted = multiplier << 5;
            multiplier = shifted - multiplier;
        }
        hashCode = hash;
    }
    return hashCode;
}

Sinta-se à vontade para verificar você mesmo ...


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 :-).


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.


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.


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.





hashcode