when que para metodo and java equals hashcode hashset

java - que - Hashcode y Equals para Hashset



para que es el hashcode (6)

Esta pregunta ya tiene una respuesta aquí:

Por favor aclarar mi duda en Hashset. Considere 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 lo 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<Person> sset=new HashSet<Person>(); sset.add(obj1); sset.add(obj4); sset.add(obj2); sset.add(obj3);

Estoy recibiendo 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 comprueba el resto de los objetos?

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

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

la 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 a entrar en el método equals () a pesar de que se agregan dos objetos al conjunto hash que tiene el mismo código hash.

Pregunta 3 : iteré el valor anterior e imprimí el contenido, pero ni el código de hash ni los iguales fueron llamados. ¿Cuándo es realmente útil anular el código de hash y el método de iguales?

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


  1. No hay necesidad de llamar a equals si hashCode difiere.
  2. No hay necesidad de llamar a hashCode si (obj1 == obj2) .
  3. No hay necesidad de hashCode y / o equals igual para iterar, no estás comparando objetos
  4. Cuando sea necesario distinguir entre objetos.

Creo que todas sus preguntas serán respondidas si entiende cómo funcionan los Conjuntos, y en particular los HashSets. Un conjunto es una colección de objetos únicos, con Java que define la singularidad en el sentido de que no es igual a otra cosa (igual a devuelve falso).

El HashSet aprovecha los códigos hash para acelerar las cosas. Se supone que dos objetos que son iguales tendrán el mismo código hash. Sin embargo, no supone que dos objetos con el mismo código hash signifiquen que son iguales. Esta es la razón por la que cuando detecta un código hash en colisión, solo se compara con otros objetos (en su caso, uno) en el conjunto con el mismo código hash.


De acuerdo con el código fuente de jdk de javasourcecode.org, HashSet usa HashMap como su implementación interna, el código sobre el método de colocación de HashSet se encuentra 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<K,V> 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 poner el método de equivalencia de llamada del objeto.



Debug HashSet con todos sus métodos y verá cómo funciona


Porque en el segundo caso, si agrega la misma referencia dos veces y HashSet verifica esto 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, los equals se llamarán solo si el hash de la clave que se agrega es igual a la clave ya presente en el conjunto y las referencias de estos dos son diferentes.