Contract Java quy định:
1. Nếu a.equals(b) == true → a.hashCode() == b.hashCode() bắt buộc.
2. Ngược lại không bắt buộc — hai object khác nhau có thể có cùng hashCode (hash collision).
Vì sao phải override cả hai:
HashMap/HashSet tìm bucket bằng hashCode() trước, rồi mới dùng equals() để tìm đúng entry trong bucket. Override equals() mà không override hashCode() → hai object "bằng nhau" về nội dung nhưng nằm ở hai bucket khác nhau → map.get() không tìm được.
class Point {
int x, y;
// CHỈ override equals — thiếu hashCode
@Override
public boolean equals(Object o) {
if (!(o instanceof Point p)) return false;
return x == p.x && y == p.y;
}
}
var map = new HashMap<Point, String>();
var p1 = new Point(1, 2);
map.put(p1, "A");
map.get(new Point(1, 2)); // null — vì hashCode() khác nhau dù equals() trả trueCách override đúng:
@Override
public int hashCode() {
return Objects.hash(x, y); // Java 7+
}Quy tắc chọn field: dùng cùng tập field với equals(). Field dùng trong hashCode() nên immutable — nếu object đổi giá trị sau khi đã put vào HashMap thì entry bị "lạc".
Tóm lại: equals() định nghĩa "bằng nhau", hashCode() định nghĩa "cùng nhóm tìm kiếm" — hai thứ phải nhất quán.
Java mandates:
1. If a.equals(b) == true → a.hashCode() == b.hashCode() required.
2. The reverse is not required — two different objects may share a hashCode (hash collision).
Why both must be overridden:
HashMap/HashSet first finds the bucket via hashCode(), then uses equals() to locate the exact entry. Overriding equals() without hashCode() means two "equal" objects land in different buckets → map.get() returns null.
class Point {
int x, y;
// ONLY equals — missing hashCode
@Override
public boolean equals(Object o) {
if (!(o instanceof Point p)) return false;
return x == p.x && y == p.y;
}
}
var map = new HashMap<Point, String>();
var p1 = new Point(1, 2);
map.put(p1, "A");
map.get(new Point(1, 2)); // null — different hashCodes despite equals() returning trueCorrect override:
@Override
public int hashCode() {
return Objects.hash(x, y); // Java 7+
}Field rule: use the same fields as equals(). Those fields should be immutable — mutating an object after it has been put in a HashMap orphans the entry.
Bottom line: equals() defines "same value", hashCode() defines "same search bucket" — they must be consistent.