equals, hashCode, compareTo · Topic 4 of 6
Overriding equals without hashCode
Definition​
If you override equals but not hashCode, two equal objects usually get different hash codes. A HashSet or HashMap then looks in the wrong bucket, so it usually cannot find an object that is equal to one it already holds, and duplicates can appear.
Example code​
Equal objects with different hash codes, and the fix
import java.util.HashSet;
import java.util.Set;
class BadId {
final int value;
BadId(int value) { this.value = value; }
@Override public boolean equals(Object o) { return o instanceof BadId b && b.value == value; }
// no hashCode(): it inherits Object.hashCode(), which is different for every object
}
class GoodId {
final int value;
GoodId(int value) { this.value = value; }
@Override public boolean equals(Object o) { return o instanceof GoodId g && g.value == value; }
@Override public int hashCode() { return Integer.hashCode(value); }
}
class Demo {
public static void main(String[] args) {
BadId a = new BadId(7), b = new BadId(7);
System.out.println("equal? " + a.equals(b));
System.out.println("same hash? " + (a.hashCode() == b.hashCode())); // false: hash collections get confused
Set<GoodId> good = new HashSet<>();
good.add(new GoodId(7));
System.out.println("found? " + good.contains(new GoodId(7))); // true: equal objects share a hash
}
}
// Output:
// equal? true
// same hash? false
// found? true
Finished this page? Track your progress (saved only in your browser).