因为 Java 的散列容器(HashMap、HashSet)依赖 hashCode 定位桶,再依赖 equals 确认相等,两者必须满足契约:相等的对象必须有相等的 hashCode。只重写 equals 不重写 hashCode,会让逻辑上相等的对象散落到不同的桶,散列容器判断"集合中不存在该元素",导致重复存储或查找失败。
class Point {
int x, 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;
}
// 忘了重写 hashCode
}
Set<Point> set = new HashSet<>();
set.add(new Point(1, 2)); // Point 继承 Object.hashCode(基于地址)
set.contains(new Point(1, 2)); // false!两个相等对象落在不同桶
完整契约:equals 需满足自反、对称、传递、一致、对 null 为 false;hashCode 需满足——同一对象多次调用结果一致(equals 未变的前提下),equals 相等则 hashCode 必相等,不相等的对象 hashCode 尽量不同(非强制,但影响散列性能)。
实践:用 IDE 生成或 Objects.hash(...),且 equals 用到的字段都要参与 hashCode。追问方向:hashCode 冲突对 HashMap 性能的影响?可变对象作为 Map key 的坑?
(约 350 字)