Equality & Hashing
In Java, "equal" is two different questions. == asks about identity: is this the same object in memory. equals() asks about content: are the objects equal in meaning. For primitives == compares values directly, but for objects it checks only the reference — so two Strings or Integers that are equal in value can well be distinct instances.
Hashing is a continuation of the same story. Hash-based collections (HashMap, HashSet) first pick a bucket by hashCode(), then compare equals() inside it. From this grows a strict contract: equal objects must return the same hash. Override equals() and forget hashCode() and you lose the key: the object lands in one bucket but is searched for in another. The full map lives in the layers below.
Topic map
- == vs equals() — reference equality versus logical equality, and why
Stringand wrappers always useequals(). - The equals/hashCode contract — why you override both together, and how equal objects must share a
hashCode.
Common traps
| Mistake | Consequence |
|---|---|
Comparing String content with == | Sometimes "works" on interned literals and silently breaks with new String() |
Assuming equals() compares content by default | In Object it behaves like == — comparing references until overridden |
Overriding equals() but not hashCode() | The key is lost in a HashMap: different buckets on put and get |
| Treating collisions as impossible | Distinct objects MAY share a hash — the reverse half of the contract is not guaranteed |
Putting mutable fields in hashCode() | After a field changes, the object "relocates" to another bucket and becomes unfindable |
Comparing Integer wrappers with == | True only within the −128..127 cache; beyond it, false |
Skipping the null/type check in equals() | NullPointerException or ClassCastException instead of false |
Interview relevance
This comes up on almost every junior interview, but the check is a mental model rather than recall: do you understand the difference between identity and content, and how that difference drives hash-based collections.
Typical checks:
- How
==differs fromequals()for objects and for primitives. - What
Object.equals()does by default and why you override it. - Both halves of the
equals/hashCodecontract and why the methods are overridden together. - Why a key is lost in a
HashMapwhen onlyequals()is overridden. - The
==-on-Integertrap with the−128..127cache.
Common wrong answer: "== and equals() are the same thing, just different syntax." That opens the discussion that for objects == compares references while equals() compares content — which is exactly why new String("a") == new String("a") is false while .equals() is true.