Detailed explanation
In Java, hashCode() is a method inherited from Object that returns a 32-bit int representing an object's hash value. Its main purpose is to support efficient lookup, insertion, and removal in hash-based collections such as HashMap and HashSet. It is not a unique identifier or necessarily a memory address. A useful hash function distributes objects across buckets reasonably evenly, reducing the number of equality comparisons required. Good distribution supports expected constant-time operations, although hashing alone does not guarantee that performance.
The central contract is that if a.equals(b) is true, a.hashCode() must equal b.hashCode(). The reverse is not required: unequal objects may have the same hash code, which is called a collision. Repeated calls on the same object must return the same hash code during an execution, provided information used in equals() has not changed. The result need not remain identical across separate executions. Therefore, whenever you override equals() to implement logical equality, you should also override hashCode() consistently.
Under the hood, HashMap derives an internal hash from the key's hashCode() and uses it to select a bucket. It then checks candidate entries using stored hashes and reference identity or equals() to find a matching key. HashSet uses a backing HashMap to store its elements as keys. If logically equal objects produce different hashes, a lookup may miss an existing entry, or a set may retain logically duplicate elements. Collisions are different: collections handle them by distinguishing keys, so equal hash codes do not make unequal objects equal.
For a Point whose equality compares x and y, Objects.hash(x, y) is a straightforward consistent implementation. Its equals() must actually check identity, null and type compatibility, and coordinate values; the supplied always-true placeholder is not valid. Avoid changing equality-relevant fields while an object is a map key or set element: the stored entry is not automatically relocated when its hash changes. Interviewers typically expect you to explain the one-way implication, distinguish collisions from contract violations, and connect the contract to real collection behaviour rather than merely recite it.
Key points to remember
- hashCode() returns an int used to organise objects in hash-based collections.
- Equal objects must have equal hash codes; equal hash codes do not imply equal objects.
- Hash codes must stay consistent within an execution while equality-relevant information remains unchanged.
- Override hashCode() whenever you override equals(), using a strategy consistent with logical equality.
- Prefer immutable keys: changing equality-relevant state after insertion can break lookup.
Common mistakes candidates make
- Overriding equals() but retaining Object.hashCode(), allowing logically equal instances to produce different hashes.
- Assuming hash codes are unique or that a collision violates the contract.
- Mutating fields used by equals() and hashCode() while an object is stored as a key or set element.
Likely follow-up questions
Is returning a constant from hashCode() valid?
Yes, a constant hash code satisfies the hashCode() contract because equal objects necessarily receive the same value. However, it causes collisions for every key and can substantially degrade hash-collection performance.
What happens if two unequal keys have the same hash code?
They collide, but HashMap can still store both as separate keys. It uses identity or equals() checks to distinguish matching-hash candidates rather than treating the hash code as proof of equality.
How should a mutable map key be updated safely?
Remove the entry before changing equality-relevant fields, then reinsert it after the change. Prefer an immutable key or a separate immutable identifier so that updates cannot invalidate lookups.
Interview tip: State the equal-objects rule first, explain a HashMap lookup, and finish with the Point example and the mutable-key warning.
