equals() vs hashCode() ⚖️
Override one, you must override the other.
These two methods define object identity. Override equals() without hashCode() and your objects mysteriously vanish from HashMap and HashSet.
The contract
- If
a.equals(b)is true, thena.hashCode() == b.hashCode()must hold. - Equal hash codes do not require equality (collisions are fine).
- Both must use the same fields.
Do it the easy way
A record generates correct equals, hashCode, and toString for you:
record Point(int x, int y) {}For a regular class, derive both from the same fields:
final class Point {
final int x, y;
Point(int x, int y) { this.x = x; this.y = y; }@Override public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Point p)) return false;
return x == p.x && y == p.y;
} @Override public int hashCode() {
return Objects.hash(x, y);
}
}
instanceof pattern matching (Java 16+) handles the null check and cast in one line.
Get Marcelo Domingues’s stories in your inbox
Join Medium for free to get updates from this writer.
TL;DR: Always override equals() and hashCode() together using identical fields — or just use a record.
Reach for a record next time you need a value object and skip the boilerplate entirely.







