Como se señaló Abimaran Kugathasan, la implementación HashMap utiliza hash cubos para buscar de manera eficiente las llaves, y sólo utiliza equals() para comparar las claves en el juego de hash-cubo contra la clave dada. Vale la pena señalar que las claves se asignan a los hash-buckets cuando se agregan a un HashMap. Si altera 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 hash-bucket correcto; e intentando usar una clave coincidente para acceder al mapa, encontrará el hash-bucket adecuado, pero no contendrá la clave alterada.
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 dar lugar a un comportamiento bastante extraño. Puede establecer un punto de interrupción justo antes de la clave de confirmación de mapeo (clave), y ver que el valor de la tecla coincida con una clave en el mapa, y sin embargo no se invocarán los equivalentes() de la clave y containsKey() devolverá falso.
Como se indica aquí https://stackoverflow.com/a/21601013, en realidad hay una advertencia de JavaDoc para Map con respecto al uso de tipos mutables para las claves. Los tipos de mapas sin hash no tendrán este problema en particular, pero podrían tener otros problemas cuando las claves se modifiquen en el lugar.
Más específicamente, si implementa el método 'igual', debe implementar' hashcode' uno ... como está escrito en el manual :) –
Encontré una manera fácil de usar el asistente en Eclipse, simplemente ejecutando Source | Genera hashCode() y es igual a(). –