equals() and hashCode() Contract
Fast recall
Quick revision
Core answer
hashCode() picks the bucket, then equals() matches the key inside it. If you override only equals(), two equal objects may get different hash codes and land in different buckets, so lookups fail. The contract: equal objects MUST have equal hash codes — override both, using the same fields.Whether you understand the two-step lookup and the equals/hashCode contract
Overriding only equals() and being surprised that map.get(key) returns null for an equal object
State the contract precisely: equal objects must have equal hashes; unequal objects may share a hash (collision)
Interview-ready guide
Interview answer
It comes down to how HashMap finds things, which is a two-step process.
First it calls hashCode on the key to decide which bucket to look in. Then, inside that bucket, it calls equals to find the exact key among any that collided there. Because both steps are involved, both methods have to be overridden and they have to agree.
The formal rule is the equals-hashCode contract: if two objects are equal according to equals, they must return the same hashCode. The reverse is not required — two unequal objects are allowed to share a hash code, that's just a collision and HashMap handles it. Now picture what happens if you override only equals.
You create a key, put a value in, then create a second key that's logically equal and call get. Since you didn't override hashCode, the two keys use the default identity hash, so they almost certainly produce different hash codes, land in different buckets, and the map looks in the wrong bucket and returns null. Your equal key is effectively invisible.
If you override only hashCode, they reach the same bucket, but the default equals compares object identity, so it still says they're different. So you must override both, and crucially, compute them from the same set of fields. equals, or even better, use a Java record, which generates a correct equals and hashCode for you automatically.
One more warning: avoid mutable keys, because if a field used in the hash changes after you've inserted the key, its hash changes and you'll never find it again.
equals() and hashCode() Contract
Direct Answer
Because HashMap finds an entry in two steps: hashCode() picks the bucket, then equals() matches the key inside it. If you override only equals(), two equal objects may get different hash codes and land in different buckets, so lookups fail. The contract: equal objects MUST have equal hash codes — override both, using the same fields.
Common Mistakes & Pitfalls
- Overriding only
equals(). The most common bug —getreturns null for an equal key. - Using different fields.
hashCode()andequals()must use the same fields. - Mutable keys. If a key's fields change after insertion, its hash changes and it's lost in the map.
- Hand-writing buggy hashCode. Prefer
Objects.hash(...)or arecordto avoid mistakes.
Check your understanding
Answer these without looking back at the article.
- What is the default hashCode() implementation?
- How does Lombok @EqualsAndHashCode work?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.