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.