关于HashMap中put调用equals方法的时机及触发主体的疑问
HashMap中put方法调用equals的时机疑问解答
嘿,作为刚接触HashMap的新手,你观察得特别仔细!这两个问题其实都是HashMap底层工作机制的核心点,咱们一步步拆解清楚:
疑问1:为何不是每次put都调用equals方法检查成员相等性?
HashMap的核心设计是用哈希表实现高效存储与查找,它的工作逻辑是这样的:
- 调用
put(key, value)时,第一步会先调用key.hashCode()计算哈希值,用这个值确定该key要放入的“桶”(哈希表中的一个位置)。 - 如果目标桶是空的,HashMap会直接把新键值对放进去,完全不需要调用
equals——因为没有任何元素需要对比。 - 只有当目标桶里已有元素时,才会进一步判断:先对比新key和桶内已有元素的hashCode,如果hashCode不一样,说明肯定不是同一个key,直接放入桶中;如果hashCode相同,才会调用
equals方法确认两个key是否真的相等(因为不同对象可能出现hashCode碰撞)。
回到你的代码场景:
- Line1的Student对象hashCode为1,放入桶A;
- Line2的StudentId是2,hashCode为2,对应空桶B,直接放入,无需调用equals;
- Line3的StudentId是3,hashCode为3,对应空桶C,直接放入,无需调用equals;
- Line4的StudentId是1,hashCode和Line1的一致,对应已有元素的桶A,这时候才需要调用
equals判断是否为同一个key,所以你看到了equals的打印日志。
简单总结:equals是用来解决hashCode碰撞的“兜底判断”,只有当hashCode相同的时候才会被调用,这样能极大减少不必要的对象对比,提升HashMap的性能。
疑问2:谁触发了Student类equals方法的调用?
是HashMap的put方法底层逻辑主动触发的。具体来说:
HashMap的put方法实际会调用底层的putVal方法,当发现目标桶内已有元素时,会遍历桶内的元素(可能是链表节点或红黑树节点),对每个元素执行以下操作:
- 先比较当前元素与新元素的hashCode是否相等;
- 如果hashCode相等,再调用
equals方法判断两个对象是否真正相等; - 如果equals返回true,就用新value替换旧value;如果返回false,就把新元素添加到桶内(链表挂尾部、红黑树插入对应位置)。
你的代码里,Line4的Student对象和Line1的hashCode相同,所以HashMap主动调用了你重写的equals方法,这就是你看到equals被调用的原因。
额外小提醒
你重写的hashCode只依赖StudentId,equals也仅判断StudentId,这意味着只要StudentId相同,无论Name和City是什么,HashMap都会认为是同一个key。如果这不是你预期的逻辑,记得把Name和City也加入到hashCode和equals的判断逻辑中哦!
内容的提问来源于stack exchange,提问作者user2746466
相关产品推荐
相关产品推荐

