web-dev-qa-db-fra.com

Pourquoi le hashCode () d'un ArrayList change-t-il chaque fois que vous ajoutez un nouvel élément?

Selon ma compréhension de ArrayList, la capacité par défaut est de 10 et lorsqu'elle augmente au-delà de 10, elle créera un nouvel objet avec une nouvelle capacité, etc.

Donc, par curiosité, j'ai tapé le programme suivant pour vérifier hashcode() pour ArrayList objet:

public class TestCoreJava {

    public static void main(String [] args){

        ArrayList al = new ArrayList();

        for(int i=0;i<15;i++){

            al.add("Temp"+i);
            System.out.println("Hashcode for "+i+" element "+al.hashCode());
        }
    }
}

Selon le scénario ci-dessus, lorsque je ne définis pas la capacité initiale pour ArrayList, la valeur par défaut serait 10. Ainsi, tout en ajoutant le 11e élément, cela créera un nouvel objet et augmentera la capacité de ArrayList.

Quand j'imprime le hashcode pour l'objet ArrayList, il donne à chaque fois une nouvelle hashcode().

Voici l'o/p:

Hashcode for 0 element 80692955
Hashcode for 1 element -1712792766
Hashcode for 2 element -1476275268
Hashcode for 3 element 1560799875
Hashcode for 4 element 1220848797
Hashcode for 5 element -727700028
Hashcode for 6 element -1003171458
Hashcode for 7 element -952851195
Hashcode for 8 element 607076959
Hashcode for 9 element 1720209478
Hashcode for 10 element -6600307
Hashcode for 11 element -1998096089
Hashcode for 12 element 690044110
Hashcode for 13 element -1876955640
Hashcode for 14 element 150430735

Selon le concept de capacité par défaut, jusqu'au 10ème élément, il devrait avoir imprimé la même hashcode() car aucun nouvel objet ne doit être créé avant ce point, mais ce n'est pas le cas.

19
suyash

Le hashCode de ArrayList est une fonction du hashCode de tous les éléments stockés dans le ArrayList, donc il ne change pas lorsque la capacité change, il change chaque fois que vous ajoutez ou supprimez un élément ou mute l'un des éléments d'une manière qui change son hashCode.

Voici l'implémentation Java 8 (elle est en fait implémentée dans AbstractList):

public int hashCode() {
    int hashCode = 1;
    for (E e : this)
        hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
    return hashCode;
}

BTW, c'est le code exact qui apparaît dans le Javadoc de hashCode() de l'interface List:

int Java.util.List.hashCode ()

Renvoie la valeur du code de hachage pour cette liste. Le code de hachage d'une liste est défini comme étant le résultat du calcul suivant:

int hashCode = 1;
for (E e : list)
    hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
42
Eran

hashCode des implémentations de List est défini en termes de hashCode de ses éléments . Cela signifie que pour que ArrayList soit une implémentation List conforme, il faut que hashCode change lorsque son changements de contenu.

Plus généralement: pour les objets mutables, le hashCode devrait changer chaque fois qu'ils changent d'une manière qui ne les rendrait pas equal à leur état précédent.

Vous semblez supposer qu'il utilise le par défaut hashCode de Object, ce qui n'est pas le cas.

De plus, même si ArrayList n'a pas implémenté hashCode, le code de hachage par défaut (également appelé code de hachage d'identité ) d'un ArrayList ne serait pas changer si le tableau interne a été réalloué, comme l'objet ArrayList lui-même reste le même, seul l'objet tableau interne (auquel vous n'avez pas accès directement) sera remplacé par un nouveau.

5
Joachim Sauer

L'explication peut être trouvée en regardant les documents pour hashCode

Si deux objets sont égaux selon la méthode equals (Object), l'appel de la méthode hashCode sur chacun des deux objets doit produire le même résultat entier.

Lorsqu'un ArrayLists change de contenu, il change également les autres objets auxquels il est égal. Afin de remplir cette partie du contrat de Object, un ArrayList doit avoir son hashCode changer lorsque le contenu change, ou avoir chaque ArrayList ont le même hashCode. Afin de le rendre quelque peu utile, ils ont évidemment opté pour le premier. Cela peut être vérifié en regardant List's docs .

Renvoie la valeur du code de hachage pour cette liste. Le code de hachage d'une liste est défini comme étant le résultat du calcul suivant:

 int hashCode = 1;
 for (E e : list)
     hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());

Cela garantit que list1.equals (list2) implique que list1.hashCode () == list2.hashCode () pour deux listes, list1 et list2, comme requis par le contrat général d'Object.hashCode ().

2
resueman