为什么重写equals必须重写hashcode方法
为什么重写 equals 必须重写 hashCode?
一句话先行:
你改了“怎么判相等”,就必须同步改“怎么分桶”。
一、先立三条铁律(这是 JVM 的宪法)
Java 对 equals 和 hashCode 有明确约定:
1️⃣ equals 相等 → hashCode 必须相等
2️⃣ hashCode 相等 → equals 不一定相等
3️⃣ 只要参与哈希容器,就必须遵守 1️⃣
这不是建议,是契约。
二、Object 默认实现在干嘛?
equals
1 | public boolean equals(Object obj) { |
👉 比的是 内存地址
hashCode
1 | public native int hashCode(); |
👉 基于 对象内存特征(你可以理解成“身份证号”)
结论:
默认情况下:
同一个对象才相等,不同对象永远不相等
三、问题从哪里开始?
你在业务里重写了 equals 👇
1 |
|
含义是:
只要
name一样,我就认为两个对象相等
但你没重写 hashCode。
四、灾难发生在 HashMap 里
HashMap 的查找逻辑是这样的(重点):
1 | 1️⃣ 先算 hashCode → 找桶 |
现在来看结果:
| 对象 | name | equals | hashCode |
|---|---|---|---|
| A | neo | true | ❌ 不同 |
| B | neo | true | ❌ 不同 |
结果就是:
equals:你说它们相等 ✅hashCode:JVM 说它们不是一类 ❌
👉 被分到了不同桶
👉 HashMap 当成两个元素
👉 违背第一条铁律
五、这就是为什么“必须一起重写”
因为你改了这件事:
“什么叫相等”
却没改这件事:
“相等的对象该去哪一个桶”
一句总结:
equals决定“是不是同一个人”hashCode决定“住哪栋楼”
你不能只改身份证,不改住址
六、正确姿势(记这个就够了)
规则口诀
参与 equals 的字段,必须全部参与 hashCode
标准写法
1 |
|
或者:
1 |
|
七、一句话终极总结
重写
equals却不重写hashCode,
就等于告诉 HashMap:
“他们是同一个人,但你别把他们放一起。”
HashMap:🤯
Bug:😈
Comments




