ReviseAlgo Logo

Object-Oriented Programming

equals() and hashCode()

Deconstruct the equivalence contract (reflexive, symmetric, transitive), hash collision costs, and HashMap bucket resolutions.

Interview: Focuses on equals/hashCode contract invariants, hash collision degradation, and correct contract overrides.

Last Updated: June 13, 2026 12 min read

The equals() and hashCode() contract governs object comparison and hash-based collections in Java. Violating this contract causes silent data corruption in HashMap and HashSet.

Core Idea

If two objects are equal according to equals(), they must return the same hashCode() integer. The reverse is not required.

Why It Matters

Failing to override hashCode alongside equals makes objects disappear from HashMaps, as lookups search the wrong buckets.

Interview Lens

Tests equals properties (reflexivity, symmetry, transitivity), hash collision resolution steps, and HashMap bucket distributions.

The Equivalence Contract

An implementation of equals() must satisfy five equivalence properties:

  • Reflexive: x.equals(x) must return true.
  • Symmetric: If x.equals(y) is true, then y.equals(x) must return true.
  • Transitive: If x.equals(y) is true and y.equals(z) is true, then x.equals(z) must return true.
  • Consistent: Repeated invocations of equals() must return the same result, provided no information used in comparison is modified.
  • Null-Comparison: x.equals(null) must return false for any non-null reference x.

Hash Collisions and HashMap Bucket Resolutions

When you put an object in a HashMap, the map uses the object's hashCode() to calculate which bucket index to store the entry in.

Hash Collision: Occurs when two unequal objects return the same hashcode. They resolve to the same bucket index:

  • Chaining: The bucket stores colliding elements in a linked list. Lookup costs degrade from O(1) to O(N).
  • Treeification (Java 8+): If a bucket's collision list exceeds a threshold (8 elements) and the map's total capacity is at least 64, the JVM converts the list into a self-balancing Red-Black Tree, improving lookup costs to O(log N).

Common Pitfalls

  • Overriding equals without hashCode: The classic error. Objects are added to the map but cannot be found during lookups because they search different buckets.
  • Using mutable fields in hashcodes: Modifying fields that are used to compute the hashCode after the object has been added to a Map. The object's bucket index changes, making it lost inside the map.
  • Incorrect Parameter Type: Writing public boolean equals(User other) instead of overriding public boolean equals(Object other), which overloads the method instead of overriding it.

Best Practices

  • Always override hashCode() whenever you override equals(). Use the same fields for both calculations.
  • Use Objects.equals(a, b) and Objects.hash(fields...) to write clean, null-safe overrides.
  • Use immutable fields (like IDs) for equals and hashCode calculations. Avoid using mutable fields to prevent runtime lookup failures.

Interview-Relevant Information

Q1: What happens if you override equals() but not hashCode()?
Answer: It breaks the contract. Two objects that are equal could return different hashcodes. When stored in a HashMap, the objects may resolve to different buckets, allowing duplicate keys or causing get() lookups to return null.

Q2: How does HashMap resolve hash collisions in Java 8 and later?
Answer: HashMap resolves collisions using chaining. If the number of colliding elements in a bucket exceeds 8 and the map's total capacity is at least 64, the linked list is converted to a Red-Black Tree, improving search times from O(N) to O(log N).

Quick Checklist

Can you implement the equals contract, write null-safe comparisons, explain HashMap treeification thresholds, and prevent lost keys in Maps? If yes, you understand equals and hashCode.

Use Cases

Implementing database entity keys that map to unique lookup collections.

Designing secure caching keys inside memory-bounded tables.

Common Mistakes

Overriding equals() but failing to define a matching hashCode() method.

Using mutable properties in hash calculations, causing keys to get lost in HashMaps.