Java equals() and hashCode() Contract — The Complete Visual Guide
Understanding why HashMap behaves differently when you override hashCode() and equals() — with 5 interactive scenarios that show exactly what happens inside the bucket chain.
Why does this matter?
Every Java developer writes Map<SomeObject, Value> at some point. But if you've ever seen your HashMap hold duplicate entries or silently drop data, the culprit is almost always a broken equals/hashCode contract.
How HashMap stores keys
When you call map.put(key, value), Java first calls key.hashCode() to find a bucket index. If the bucket is empty, the entry goes straight in. If the bucket already has an entry, Java walks the chain calling key.equals(existing) on each node:
- If
equals()returnstrue→ it's the same key → replace the value - If
equals()returnsfalse→ different key → chain a new node
This means hashCode() routes you to the right neighbourhood, and equals() finds the exact house. If either is wrong, you get unexpected behaviour.
The interactive scenarios below
Use the scenario tabs in the visualizer below to step through five distinct cases. Each one shows the bucket layout, step-by-step trace, and the resulting map.size(). By the end, the contract will be crystal clear.