equals() vs hashCode() in Java

equals() and hashCode() are fundamental methods defined in the java.lang.Object class.

They play a critical role in:

  • Object comparison
  • Collections (HashMap, HashSet)
  • Correct behavior of domain objects

equals()

equals() is used to check logical equality between two objects.

Default implementation in Object:

public boolean equals(Object obj) {
    return this == obj;
}

This means:
Default equals() checks reference equality, not content.


hashCode()

hashCode() returns an integer hash value representing the object.

Used by:

  • HashMap
  • HashSet
  • Hashtable

Default implementation:

  • Usually derived from memory address
  • Different objects → different hash codes

Java defines a strict contract between equals() and hashCode().

The Contract

1️⃣ If two objects are equal according to equals()

👉 they must have the same hashCode()

2️⃣ If two objects have the same hashCode()

👉 they may or may not be equal

Why This Contract Exists

Hash-based collections work in two steps:

  • Use hashCode() to find the bucket
  • Use equals() to find the exact object

If this contract is broken:

  • Objects become unreachable
  • Data loss happens
  • Bugs are very hard to detect

Overriding only one breaks the contract.

Case 1️⃣ Override equals() ONLY ❌

@Override
public boolean equals(Object o) {
return this.id == ((Customer)o).id;
}

But hashCode() is still default.

Result:

  • equals() → true
  • hashCode() → different

HashSet treats them as different objects ❌

Case 2️⃣ Override hashCode() ONLY ❌

@Override
public int hashCode() {
return id;
}

But equals() still uses reference comparison.

Result:

  • Same bucket
  • equals() fails

Duplicate objects ❌


Case 3️⃣ Override BOTH (Correct) ✅

@Override
public boolean equals(Object o) {

if (this == o) return true;

if (!(o instanceof Customer)) return false;

Customer c = (Customer) o;
return id == c.id;
}

@Override
public int hashCode() {
return Objects.hash(id);
}

✔ Correct behavior
✔ Works in all collections

Where This Matters the Most

  • HashMap
  • HashSet
  • ConcurrentHashMap
  • Hibernate entities
  • Cache keys

In enterprise apps:

  • Incorrect equals/hashCode = production bugs

Where equals() DOES content comparison by default

  • 1️⃣ String
  • 2️⃣ Wrapper Classes
  • 3️⃣ Enum
  • 4️⃣ Record (Java 16+)
  • 5️⃣ Collection Implementations

This site uses Just the Docs, a documentation theme for Jekyll.