基础篇九 重写了 equals 却不重写 hashCode,你的对象在 HashMap 里就“人间蒸发“了?
文章目录一、先说结论这是 HashMap 惹的祸二、翻车现场三、HashMap 找对象的流程四、正确姿势一起重写五、回到全貌三条规则刻进脑子六、回答技巧与点评标准回答加分回答面试官点评个人网站你有没有遇到过这种灵异事件明明把对象放进 Map 了用get()却取不出来对象就像人间蒸发了一样。别慌这不是 Bug大概率是你重写了equals()却忘了重写hashCode()。这俩是绑定的CP拆开就会出事。一、先说结论这是 HashMap 惹的祸Java 有一条铁律如果两个对象 equals 相等那它们的 hashCode 必须相等。反过来不要求——hashCode 相等的两个对象equals 不一定相等哈希冲突嘛。但如果你只重写equals()不重写hashCode()就会打破这条规则两个相同的对象算出了不同的 hashCodeHashMap 找错桶自然就取不出来了。二、翻车现场classPerson{Stringname;Person(Stringname){this.namename;}Overridepublicbooleanequals(Objecto){if(thiso)returntrue;if(!(oinstanceofPerson))returnfalse;returnname.equals(((Person)o).name);}// ❌ 没重写 hashCode()}MapPerson,StringmapnewHashMap();map.put(newPerson(张三),工程师);Stringresultmap.get(newPerson(张三));System.out.println(result);// null 明明放进去了啊两个new Person(张三)equals 是 true但 hashCode 不一样。HashMap 先用 hashCode 找桶找错了equals 根本没机会上场。三、HashMap 找对象的流程get(key) │ ├─ 1. 计算 key.hashCode() → 定位桶 ├─ 2. 遍历桶内链表/红黑树 ├─ 3. 用 key.equals() 逐个比较 └─ 4. 找到就返回没有就 nullhashCode 决定去哪个房间找equals 决定房间里哪个是对的。hashCode 不一致连房间都走错了equals 再精准也没用。就像你和朋友约在 3 号包厢吃饭结果你跑去了 5 号——你们就算长得一模一样也碰不上面。四、正确姿势一起重写classPerson{Stringname;Overridepublicbooleanequals(Objecto){if(thiso)returntrue;if(!(oinstanceofPerson))returnfalse;returnname.equals(((Person)o).name);}OverridepublicinthashCode(){returnnamenull?0:name.hashCode();}}现在两个new Person(张三)的 hashCode 相同HashMap 能找到正确的桶equals 也能匹配上完美。五、回到全貌三条规则刻进脑子equals 相等 → hashCode 必须相等否则 HashMap/HashSet 出 BughashCode 相等 → equals 不一定相等哈希冲突是正常的重写 equals 必须同时重写 hashCode这是规矩不是建议口诀equals 换了hashCode 得跟着换不然 HashMap 里找不到。六、回答技巧与点评标准回答因为 HashMap、HashSet 等集合先用 hashCode 定位桶再用 equals 比较对象。如果只重写 equals 不重写 hashCode两个逻辑相同的对象可能算出不同的 hashCode被分到不同的桶里导致 get 不到、contains 失效。Java 规范要求 equals 相等的对象 hashCode 必须相等所以两个方法必须一起重写。加分回答提到 Set 也会出问题HashSet底层就是HashMap同样的坑提到 Objects.equals/hashCodeJDK 7 推荐用Objects.equals()和Objects.hash()简化代码提到 Lombok 的 EqualsAndHashCode自动生成不容易漏面试官点评这道题表面考的是你知道吗实际考的是你有没有真正用过 HashMap。能讲清 HashMap 的查找流程hashCode 定桶 → equals 比较说明你是理解原理的而不是死记硬背。如果还能举出实际踩坑经历那就更有说服力了。原文阅读内容有帮助点赞、收藏、关注三连评论区等你