相等对象必须有相同哈希码,即若a.equals(b)为true,则a.hashCode()与b.hashCode()必须相等;hashCode计算字段须与equals中实际比较的字段完全一致,且不可含可变字段。

必须用相同字段计算,且逻辑严格对齐——这是配套重写的铁律。
核心原则:相等对象必须有相同哈希码
如果 a.equals(b) 返回 true,那么 a.hashCode() 和 b.hashCode() 必须完全相等。这是 Java 规范强制要求的契约,不是建议。
违反它会导致:
- 对象存进 HashSet 后,contains() 找不到
- HashMap 中用逻辑相同的 key 查不到已存的 value
- ConcurrentHashMap 或 LinkedHashSet 行为异常
字段选择:只用 equals 中参与比较的那些
hashCode 的计算字段必须和 equals 中实际比对的字段完全一致。多一个、少一个、顺序不同,都可能破坏一致性。
立即学习“Java免费学习笔记(深入)”;
例如,若 equals 只比较 id 和 name:
- ✅ 正确:return Objects.hash(id, name);
- ❌ 错误:return Objects.hash(id, name, age);(age 没参与 equals 判断)
- ❌ 错误:return id.hashCode();(漏了 name)
写法推荐:用 Objects 工具类保安全
避免手写哈希算法出错,也规避 null 值引发的 NullPointerException:
- Objects.equals(a, b) 自动处理 a 或 b 为 null 的情况
- Objects.hash(f1, f2, f3) 内部调用各字段的 hashCode(),并安全组合
示例:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(id, user.id) && Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
特别注意:别碰可变字段
如果某个字段在对象加入 HashSet 或作为 HashMap 的 key 后被修改,而它又参与了 hashCode 计算,就会导致该对象“消失”——再也无法被查到或删除。
所以:
- 优先选用不可变字段(如 final id、不可变字符串)
- 避免使用 lastModified、status 这类运行时可能变更的字段
- 若业务必须用可变字段,请确保它不参与 equals/hashCode


















