Java未成对实现equals()与hashCode()时HashMap运行异常原因咨询
equals与hashCode契约在HashMap中的运行逻辑分析
首先明确HashMap存储、查询键值对的核心执行流程:
- 调用key的
hashCode()方法计算哈希值,对数组长度取模后定位到对应的数组桶位置 - 在对应桶的链表/红黑树中,调用key的
equals()方法逐一和已有节点的key对比,只有返回true时才会判定为同一个key,执行覆盖/查询匹配逻辑
两个步骤必须同时满足,才会被HashMap认定为相同的键
场景1:仅实现hashCode()、未实现equals()的运行逻辑
- 重写的
hashCode()固定返回31,4个Employee对象的哈希值完全相同,都会被定位到同一个数组桶中 - 由于没有重写
equals(),使用的是Object类原生的equals逻辑:直接对比两个对象的内存地址。employee3和employee4是两次new出来的独立对象,内存地址不同,equals返回false,HashMap会判定为两个不同的键 - 因此4个对象全部被存入Map,
size()返回4;查询时传入employee4作为key,哈希定位到对应桶后,能找到内存地址完全匹配的employee4节点,所以返回Joe
场景2:仅实现equals()、未实现hashCode()的运行逻辑
- 重写的
equals()会对比对象的全部属性,employee3和employee4属性完全一致,equals返回true,但由于没有重写hashCode(),使用的是Object类原生的哈希值逻辑:根据对象内存地址计算哈希值 employee3和employee4内存地址不同,哈希值完全不同,会被定位到不同的数组桶中,HashMap根本不会触发两者的equals对比逻辑,直接判定为两个不同的键- 因此4个对象全部被存入Map,
size()返回4;查询时传入employee4作为key,根据它的哈希值能直接定位到存储它的桶,找到对应节点返回Joe
两个场景输出相同的核心原因
两者都违反了equals-hashCode契约:逻辑相等的两个对象(employee3和employee4)没有满足「equals返回true时hashCode必须相等」的要求,导致HashMap无法识别两者是逻辑相同的键,最终都存入了4个键值对,查询时都能匹配到employee4本身的节点,所以输出完全一致。
只有同时正确实现两个方法时,employee3和employee4才会被判定为同一个键,put时后者覆盖前者,最终size为3。
内容的提问来源于stack exchange,提问作者Jeff Cook
相关产品推荐
相关产品推荐

