Wenn Sie equals() überschreiben, um logische Gleichheit zu definieren, müssen Sie auch hashCode() überschreiben — denn hash-basierte Sammlungen (, ) beruhen auf dem Vertrag, dass . Dies zu brechen führt zu subtilen, schwer zu findenden Fehlern.
Wenn Sie equals() überschreiben, um logische Gleichheit zu definieren, müssen Sie auch hashCode() überschreiben — denn hash-basierte Sammlungen (, ) beruhen auf dem Vertrag, dass . Dies zu brechen führt zu subtilen, schwer zu findenden Fehlern.
HashMapHashSet// by default, equals() compares IDENTITY (same object?), hashCode() is based on memory address
Person p1 = new Person("Ann", 30);
Person p2 = new Person("Ann", 30);
p1.equals(p2); // false by default — different objects, even with same data
Ohne Überschreiben sind zwei Objekte mit identischem Inhalt "nicht gleich" — normalerweise nicht das, was Sie für Wertobjekte möchten.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person p = (Person) o;
return age == p.age && Objects.equals(name, p.name); // compare by CONTENT
}
@Override
public int hashCode() {
return Objects.hash(name, age); // MUST be consistent with equals()
}
Der Vertrag: Wenn a.equals(b) wahr ist, dann MUSS a.hashCode() == b.hashCode() wahr sein.
Person p1 = new Person("Ann", 30);
Person p2 = new Person("Ann", 30); // equal by our equals()
Set<Person> set = new HashSet<>();
set.add(p1);
set.contains(p2); // ❌ likely FALSE — even though p1.equals(p2)!
Warum? HashMap/HashSet verwenden zuerst hashCode(), um den richtigen Bucket zu finden, dann equals() darin. Mit dem Standard (identitätsbasierten) hashCode() landen p1 und p2 in verschiedenen Buckets, also vergleicht contains sie nie — die Menge hält sie für verschieden. Dies führt zu verwirrenden Bugs: Duplikate in einem Set, fehlgeschlagene Map-Lookups, usw.
1. equal objects → equal hash codes (REQUIRED for correctness)
2. unequal objects MAY have the same hash (collisions are allowed)
3. hashCode() must be consistent (same object → same code, unchanged)
4. equals() must be reflexive, symmetric, transitive, consistent
record Person(String name, int age) {} // records auto-generate equals/hashCode/toString!
Java records (und IDE-Generierung / Lombok) erzeugen korrektes, konsistentes equals/hashCode für Sie.
Der equals/hashCode-Vertrag ist eine der wichtigsten — und am häufigsten verletzten — Regeln in Java.
equals() ohne hashCode() zu überschreiben bricht hash-basierte Sammlungen auf Weise auf, die schwer zu debuggen sind: Objekte, die Sie für gleich halten, gehen in HashMap/HashSet „verloren
Eine Sammlung von IT-Interviewfragen mit ausführlichen Antworten — vom Junior bis zum Senior.
Spenden