Wie Abimaran Kugathasan erwähnt, ist die HashMap Implementierung verwendet Eimer Hash-effizient Schlüssel aufblicken, und nur verwendet equals() die Schlüssel in der entsprechenden Hash-Eimer vergleichen gegen den angegebenen Schlüssel. Es ist erwähnenswert, dass Schlüssel den Hash-Buckets zugewiesen werden, wenn sie zu einer HashMap hinzugefügt werden. Wenn Sie Schlüssel in einer HashMap ändern, nachdem Sie sie hinzugefügt haben, und zwar auf eine Weise, die ihren Hash-Code ändert, dann sind sie nicht im richtigen Hash-Bucket; Wenn Sie versuchen, einen übereinstimmenden Schlüssel für den Zugriff auf die Map zu verwenden, wird der richtige Hash-Bucket gefunden, der geänderte Schlüssel wird jedoch nicht enthalten sein.
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
Dies kann zu einem ziemlich merkwürdigen Verhalten führen. Sie können einen Haltepunkt kurz vor theMap.containsKey (theKey) setzen und sehen, dass der Wert von theKey mit einem Schlüssel in der Map übereinstimmt, und dennoch wird der Wert equals() des Schlüssels nicht aufgerufen, und containsKey() gibt false zurück.
Wie hier erwähnt https://stackoverflow.com/a/21601013, gibt es tatsächlich eine Warnung der JavaDoc für Map bezüglich der Verwendung von veränderbaren Typen für Schlüssel. Nicht-Hash-Map-Typen haben dieses spezielle Problem nicht, können aber andere Probleme haben, wenn Schlüssel direkt geändert werden.
genauer gesagt, wenn Sie die 'equals' Methode implementieren, sollten Sie den' hashcode' implementieren ... wie im Handbuch geschrieben :) –
Ich fand eine einfache Möglichkeit ist, den Assistenten in Eclipse zu verwenden, nur Source ausgeführt | Generiere hashCode() und equals(). –