必须同时重写 equals 和 hashcode,且二者需基于相同字段;推荐用 objects.hash 简化实现,并确保参与计算的字段不可变以避免哈希码变化导致对象丢失。

重写 hashCode 是必要的,但光重写它并不足够。
必须同时重写 equals
Java 规范明确规定:如果两个对象通过 equals 判定为相等,那么它们的 hashCode 必须相同。反之,hashCode 相同并不要求 equals 为 true(即允许哈希碰撞)。如果只重写 hashCode 而不重写 equals,会导致逻辑不一致——比如在 HashSet 或 HashMap 中,本该视为同一个键的对象可能被重复插入或无法查到。
确保 hashCode 计算基于 equals 所用的字段
hashCode 的实现必须只使用那些参与 equals 比较的字段,且计算方式要稳定(例如不能依赖可变状态或随机值)。常见错误包括:
- 用了未参与
equals判断的字段,导致等价对象哈希值不同 - 在
hashCode中调用了可能改变状态的方法(如懒加载初始化) - 字段为
null时未做安全处理,抛出NullPointerException
推荐使用工具生成,而非手写
手写容易出错,建议用 IDE(如 IntelliJ)自动生成,或使用 Objects.hash(...) 简化:
public int hashCode() {
return Objects.hash(fieldA, fieldB, fieldC);
}
它会自动处理 null,也与 Objects.equals 的语义对齐,降低出错概率。
注意不可变性与线程安全
若对象在放入哈希集合后其参与 hashCode 计算的字段被修改,会导致哈希码变化,进而使对象“丢失”(再也无法被 get 或 contains 找到)。因此,理想情况下,参与 hashCode / equals 的字段应设为 final,保证不可变。










