Hashcode e iguales para Hashset

Por favor, aclara mi duda en Hashset. Considera el siguiente código

class Person { String name; Person(String n) { name=n; } public String getName() { return name; } @Override public boolean equals(Object arg0) { System.out.println("in equals"); Person obj=(Person)arg0; System.out.println("1st "+getName()); System.out.println("2nd "+obj.getName()); if(this.getName().equals(obj.getName())) { return true; } return false; } @Override public int hashCode() { System.out.println("in hash code"); System.out.println(" value is "+Integer.valueOf(name.charAt(0))); return Integer.valueOf(name.charAt(0)); } } 

en principal tengo el siguiente código

 Person obj1=new Person("bcd"); Person obj2=new Person("cde"); Person obj3=new Person("abc"); Person obj4=new Person("abc"); 

Ahora si agrego estos objetos a hashset

 Set sset=new HashSet(); sset.add(obj1); sset.add(obj4); sset.add(obj2); sset.add(obj3); 

Estoy obteniendo esta salida

 in hash code value is 98 in hash code value is 97 in hash code value is 99 in hash code value is 97 in equals 1st abc 2nd abc 

Pregunta 1 : ¿por qué la función equals () se llama solo una vez para verificar obj3 y obj4? ¿Por qué no se verifica para el rest de los objetos?

Pregunta 2 : Si la respuesta es porque ambos tienen el mismo código hash, solo se llamará a igual, entonces ¿por qué no se llama para el código siguiente?

 sset.add(obj1); sset.add(obj4); sset.add(obj2); sset.add(obj4); 

salida es:

 in hash code value is 98 in hash code value is 97 in hash code value is 99 in hash code value is 97 

No va dentro del método equals () aunque se hayan agregado dos mismos objetos al conjunto de hash que tiene el mismo código hash.

Pregunta 3 : repetí el valor anterior e imprimí el contenido, pero no se llamaron ni hashcode ni iguales. cuando es realmente útil para anular el código hash y el método igual?

Pregunta 4 : ¿Cuándo se hashCode() y equals() ?

  1. No es necesario llamar a equals si hashCode es hashCode .
  2. No es necesario llamar a hashCode if (obj1 == obj2) .
  3. No hay necesidad de hashCode y / o equals simplemente a iterar: no estás comparando objetos
  4. Cuando es necesario distinguir entre objetos.

Creo que todas sus preguntas serán contestadas si comprende cómo funcionan Sets, y en particular HashSets. Un conjunto es una colección de objetos únicos, con la singularidad de definición de Java en el sentido de que no es igual a nada (es decir, devuelve falso).

El HashSet aprovecha los hashcodes para acelerar las cosas. Supone que dos objetos que se igualan tendrán el mismo código hash. Sin embargo, no supone que dos objetos con el mismo código hash significan que son iguales. Es por eso que cuando detecta un código hash colisionante, solo se compara con otros objetos (en su caso uno) en el conjunto con el mismo código hash.

según el código fuente jdk de javasourcecode.org, HashSet utiliza HashMap como su implementación interna, el código sobre el método put de HashSet está a continuación:

 public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; } 

La regla es, en primer lugar, verificar el hash, luego verificar la referencia y luego se ingresa el método call equals del objeto.

Porque en el segundo caso, al agregar la misma referencia dos veces y HashSet se comprueba en HashMap.put() en el que se basa HashSet :

  if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } 

Como puede ver, se equals si el hash de la clave que se agrega es igual a la clave que ya está presente en el conjunto y las referencias de estos dos son diferentes.

Debería leer sobre cómo asegurarse de que ha implementado equals y hashCode correctamente. Este es un buen punto de partida: ¿qué problemas se deben tener en cuenta al anular equals y hashCode en Java?

Por favor, depure HashSet con todos sus métodos y verá cómo funciona