java - metodo - ¿Por qué el hashCode() de un ArrayList cambia cada vez que agregas un nuevo elemento?
hashcode java (3)
Según mi entendimiento de ArrayList
, la capacidad predeterminada es 10 y cuando crezca más allá de 10, creará un nuevo objeto con nueva capacidad, etc.
Por curiosidad, escribí el siguiente programa para verificar el hashcode()
para el objeto ArrayList
:
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());
}
}
}
De acuerdo con el escenario anterior, cuando no estoy configurando la capacidad inicial para ArrayList
el valor predeterminado sería 10. Por lo tanto, al agregar el elemento 11, creará un nuevo objeto y aumentará la capacidad de ArrayList
.
Cuando imprimo el código hash para el objeto ArrayList
, está dando un hashcode()
nuevo hashcode()
cada vez.
La siguiente es la 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
De acuerdo con el concepto de capacidad predeterminada, hasta el décimo elemento, debe haber impreso el mismo hashcode()
ya que no es necesario crear ningún objeto nuevo hasta ese momento, pero no es el caso.
El hashCode
de las implementaciones de la List
se define en términos del hashCode
de sus elementos . Esto significa que para que ArrayList
sea una implementación conforme de la List
, su hashCode
debe cambiar cuando cambia su contenido.
Más generalmente: para los objetos mutables, el hashCode
debe cambiar siempre que cambien de una manera que haga que no sean equal
a su estado anterior.
Parece que estás asumiendo que usa el hashCode
de hashCode
predeterminado de Object
, que no es el caso.
Además, incluso si ArrayList
no implementó el código hash, el código hash predeterminado (también conocido como el código hash de identidad ) de un ArrayList
no cambiaría si la matriz interna se reasignara, ya que el objeto ArrayList
sigue siendo el mismo, solo el interno El objeto de matriz (al que no tiene acceso directo) se reemplazará por uno nuevo.
El hashCode
of ArrayList
es una función del hashCode
s de todos los elementos almacenados en ArrayList
, por lo que no cambia cuando cambia la capacidad, cambia cada vez que agrega o elimina un elemento o muta uno de los elementos de una manera que cambia su código hash.
Aquí está la implementación de Java 8 (en realidad se implementa en AbstractList
):
public int hashCode() {
int hashCode = 1;
for (E e : this)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
}
Por cierto, este es el código exacto que aparece en el Javadoc de hashCode()
de la interfaz de la List
:
int java.util.List.hashCode ()
Devuelve el valor del código hash para esta lista. El código hash de una lista se define como el resultado del siguiente cálculo:
int hashCode = 1;
for (E e : list)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
La explicación para esto se puede encontrar mirando los documentos para hashCode
Si dos objetos son iguales según el método equals (Objeto), entonces llamar al método hashCode en cada uno de los dos objetos debe producir el mismo resultado entero.
Cuando los contenidos de un ArrayList
cambian, también cambia a qué otros objetos es igual. Para cumplir con esta parte del contrato de Object
, una ArrayList
necesita que su hashCode
de hashCode
cambie cuando lo hace el contenido, o que cada ArrayList
tenga el mismo hashCode
. Para hacerla algo útil, obviamente optaron por la primera. Esto puede verificarse mirando los documentos de la List
.
Devuelve el valor del código hash para esta lista. El código hash de una lista se define como el resultado del siguiente cálculo:
int hashCode = 1; for (E e : list) hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
Esto garantiza que list1.equals (list2) implica que list1.hashCode () == list2.hashCode () para cualquiera de las dos listas, list1 y list2, como lo requiere el contrato general de Object.hashCode ().