HashMap internals 10: equals() and hashCode()
HashMap depends on two methods of the key:
hashCode()chooses the bucket.equals()finds the exact key inside the bucket.
The contract: objects that are equal must have equal hash codes. Equal hash codes don't have to mean equal objects.
Break it and HashMap misbehaves:
- equals() without hashCode(): two "equal" keys usually get different (identity) hash codes, so they land in different buckets. You get duplicate keys, and
get()with an equal-but-different object returnsnull. - hashCode() without equals(): equal keys reach the same bucket, but
equals()still compares identity, so you still get duplicates. - Correct: override both, using the same fields. Let your IDE generate them, use
Objects.hash, or use a record, which does it for you.
Example
class Point {
final int x, y;
Point(int x, int y) { this.x = x; this.y = y; }
@Override public boolean equals(Object o) {
return o instanceof Point p && p.x == x && p.y == y;
}
// no hashCode(): the contract is broken
}
Map<Point, String> labels = new HashMap<>();
labels.put(new Point(1, 2), "start");
System.out.println(labels.get(new Point(1, 2))); // null (almost always): different bucket
record Pt(int x, int y) {} // equals() and hashCode() generated from x and y
Map<Pt, String> ok = new HashMap<>();
ok.put(new Pt(1, 2), "start");
System.out.println(ok.get(new Pt(1, 2))); // startCommon mistake
Overriding equals() and forgetting hashCode(). The code compiles and passes simple tests, then HashMap and HashSet silently misbehave.
Under the hood
Use only fields that don't change while the object is a key (part 13), and make equals() and hashCode() agree exactly. Objects.hash is convenient but creates a small array on each call; for very hot keys, write 31 * Integer.hashCode(x) + Integer.hashCode(y) or cache the hash in an immutable class, as String does.
Check yourself
Point overrides equals() but not hashCode(). map.put(new Point(1,2), "a"); what does map.get(new Point(1,2)) usually return?
How this connects
Where this leads
Part of HashMap internals, part by part.
Was this lesson helpful?
Finished reading? Mark it complete to track your progress.