因为 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 字)