为什么重写 equals 时一定要重写 hashCode?
发布于
一、先说结论
这是 Java 的通用约定:如果两个对象通过 equals 比较相等,那么它们的 hashCode 必须相同。只重写 equals 不重写 hashCode,会破坏这个约定,导致对象在 HashMap、HashSet 等集合中行为异常。
二、HashMap 的存取过程
HashMap 先根据 key 的 hashCode 定位哈希桶,再在桶内通过 equals 判断 key 是否相等:
- put:
hashCode→ 找桶 → 桶内equals比较 → 决定覆盖还是新增。 - get:同样先算
hashCode找桶,再用equals匹配。
三、不重写会出什么问题
假设只重写了 equals(按业务字段比较内容),而用默认的 hashCode(基于对象地址):
Map<User, String> map = new HashMap<>();
map.put(new User(1L, "张三"), "data");
// 另一个内容相等的对象去查
String v = map.get(new User(1L, "张三")); // null!
两个对象 equals 相等但 hashCode 不同,get 时定位到了不同的桶,自然找不到。
四、正确做法
- 两个对象
equals为 true →hashCode必须相等。 hashCode相等的对象,equals不一定为 true(允许哈希冲突)。- 现代项目建议直接用 IDE 生成,或用 Lombok 的
@EqualsAndHashCode。