Careeroza
equals and hashCode Contract
== vs equals
== compares references (same object in memory?). equals() compares logical value. Object.equals by default is just ==, so value classes must override it.
Example
import java.util.Objects;
public class Main {
public static void main(String[] args) {
String a = new String("upi"), b = new String("upi");
System.out.println("a == b: " + (a == b));
System.out.println("a.equals(b): " + a.equals(b));
Money m1 = new Money(100, "INR"), m2 = new Money(100, "INR");
System.out.println("m1.equals(m2): " + m1.equals(m2));
System.out.println("same hashCode: " + (m1.hashCode() == m2.hashCode()));
}
}
final class Money {
private final long amount;
private final String currency;
Money(long amount, String currency) { this.amount = amount; this.currency = currency; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Money other)) return false;
return amount == other.amount && currency.equals(other.currency);
}
@Override
public int hashCode() { return Objects.hash(amount, currency); }
}Output
a == b: false a.equals(b): true m1.equals(m2): true same hashCode: true
The Contract
| Rule | Meaning |
|---|---|
| Reflexive | x.equals(x) is true |
| Symmetric | x.equals(y) ⇔ y.equals(x) |
| Transitive | x = y and y = z ⇒ x = z |
| Consistent | same answer every time if nothing changes |
| Null | x.equals(null) is false |
| hashCode | equal objects must have equal hash codes (unequal objects may collide) |
Tip: Records generate correct equals, hashCode and toString for you. IDEs (IntelliJ: Alt+Insert) and Lombok @EqualsAndHashCode can generate them for classes.