java hashmap equals containskey

Java HashMap.containsKey() no llama a equals()



(6)

Solo si 2 hashCodes iguales, se llamará a equals () durante las claves de bucle.

Esta es la respuesta correcta ... o casi. Precisamente, si 2 códigos hash chocan (ser el mismo garantiza que están obligados a chocar bajo la implementación adecuada del hashmap), solo entonces se realiza la verificación de igualdad.

Tengo un hashmap:

Map<LotWaferBean, File> hm = new HashMap<LotWaferBean, File>(); LotWaferBean lw = new LotWaferBean(); ... //populate lw if (!hm.containsKey((LotWaferBean) lw)) { hm.put(lw, triggerFiles[l]); }

El código para LotWaferBean :

@Override public boolean equals(Object o) { if (!(o instanceof LotWaferBean)) { return false; } if (((LotWaferBean) o).getLotId().equals(lotId) && ((LotWaferBean) o).getWaferNo() == waferNo) { return true; } return false; }

En mi IDE pongo puntos de interrupción en equals() pero nunca se ejecuta. ¿Por qué?


Como señaló Abimaran Kugathasan, la implementación de HashMap usa hash-buckets para buscar claves de manera eficiente, y solo usa equals () para comparar las claves en el hash-bucket correspondiente con la clave dada. Vale la pena señalar que las claves se asignan a los hash-buckets cuando se agregan a un HashMap . Si modifica las claves en un HashMap después de agregarlas, de una manera que cambiaría su código hash, entonces no estarán en el cubo de hash adecuado; e intentar usar una clave coincidente para acceder al mapa encontrará el hash-bucket adecuado, pero no contendrá la clave modificada.

class aMutableType { private int value; public aMutableType(int originalValue) { this.value = originalValue; } public int getValue() { return this.value; } public void setValue(int newValue) { this.value = newValue; } @Override public boolean equals(Object o) { // ... all the normal tests ... return this.value == ((aMutableType) o).value; } @Override public int hashCode() { return Integer.hashCode(this.value); } } ... Map<aMutableType, Integer> aMap = new HashMap<>(); aMap.put(new aMutableType(5), 3); // puts key in bucket for hash(5) for (aMutableType key : new HashSet<>(aMap.keySet())) key.setValue(key.getValue()+1); // key 5 => 6 if (aMap.containsKey(new aMutableType(6)) doSomething(); // won''t get here, even though // there''s a key == 6 in the Map, // because that key is in the hash-bucket for 5

Esto puede resultar en un comportamiento bastante extraño. Puede establecer un punto de interrupción justo antes de que laMap.containsKey (theKey), y ver que el valor de theKey coincida con una clave en elMap, y sin embargo no se llame a la clave equals (), y contieneKeyKey () devuelva false.

Como se indica aquí https://.com/a/21601013 , en realidad hay una advertencia del JavaDoc para el Mapa con respecto al uso de tipos mutables para las claves. Los tipos de mapas no hash no tendrán este problema en particular, pero podrían tener otros problemas cuando las claves se modifiquen en el lugar.


Intente poner un punto de interrupción en hashCode ().

Si el hashCode () de dos objetos en un mapa devuelve el mismo número, se llamará a equals para determinar si son realmente iguales.


JVM comprueba el grupo de hashcode del hashcode de ese objeto, si hay más objetos con el mismo hashcode, solo se ejecutará el método equals (). Y, el desarrollador debe seguir el contrato correcto entre los métodos hashCode () y equals ().


Por cierto, su método igual es probablemente incorrecto. En caso de que se LotWaferBean , su método equals aceptará la instancia de la subclase, pero también lo hará su subclase?

Será mejor que lea:

@Override public boolean equals(Object o) { if (o == null || o.getClass() != getClass()) { // << this is important return false; } final LotWaferBean other = (LotWaferBean)o; return other.getLotId().equals(lotId) && other.getWaferNo() == waferNo); }


Solo si 2 hashCodes iguales, se llamará a equals() durante las claves de bucle.