web-dev-qa-db-fra.com

Qu'est-ce qui se cache derrière la méthode hashCode () pour String en Java?

J'ai étudié les méthodes hashCode() dans Java et j'ai trouvé celle de la classe String étrange. Le code source est le suivant:

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

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

Le code lui-même est assez simple. Mais je me demande quelle est la raison du calcul du code de hachage de cette façon?
Pourquoi choisir 31?
Pourquoi partir de 0 au lieu de value.length - 1?
Y a-t-il une garantie que cela rendrait les hashcodes moins susceptibles d'entrer en collision les uns avec les autres?

29
HarryLv

Oui, la probabilité de collision de hashcode est très faible car, par exemple, dans le cas de String, cela dépend de la valeur de la chaîne. Si nous ne créons pas de chaîne avec un nouvel opérateur, alors si la nouvelle chaîne a la même valeur que celle déjà présente, alors le nouvel objet String n'est pas créé, il se réfère à l'ancienne valeur du tas et dans ce cas, seule la valeur de hashCode sera être le même que prévu.

Le contrat général de hashCode est:

Chaque fois qu'elle est invoquée plusieurs fois sur le même objet lors de l'exécution d'une application Java, la méthode hashCode doit toujours renvoyer le même entier, à condition qu'aucune information utilisée dans des comparaisons égales sur l'objet ne soit modifiée Cet entier n'a pas besoin de rester cohérent d'une exécution d'une application à une autre exécution de la même application.

From Java 1.2, la classe Java.lang.String implémente son hashCode () en utilisant un algorithme de somme de produits sur tout le texte de la chaîne. [2] Étant donné une instance s de Java.lang. La classe de chaîne, par exemple, aurait un code de hachage h(s) défini par

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

où les termes sont additionnés en utilisant Java 32 bits int addition, s [i] désigne le ième caractère de la chaîne, et n est la longueur de s.

Pour votre référence dans Apache Harmony, la méthode hashCode est:

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;
}
4
Shreyos Adikari