1. hashCode 和 equals 的关系

  • equals() 判断两个对象逻辑是否相等。

  • hashCode() 返回对象的哈希码,用于哈希表快速定位。

  • 规范要求:

    • 如果 obj1.equals(obj2) 返回 true,则必须保证 obj1.hashCode() == obj2.hashCode()

    • 反之哈希码相同,不一定 equals 相同(允许哈希碰撞)。


2. 什么是哈希碰撞(Hash Collision)?

  • 不同对象经过哈希函数计算后,得到相同的哈希值,称为哈希碰撞。

  • 哈希表在定位桶时会遇到冲突,内部通过链表或红黑树遍历来区分。

  • 这是哈希表必须处理的正常现象。


3. 为什么引入 hashCode?

  • 方便快速查找:避免遍历,定位桶的位置,查找效率接近 O(1)。

  • 降低比较成本:先比较哈希码,不同哈希码直接判定不相等。

  • 实现复杂数据结构和算法的基础。


4. HashMap 和 HashSet 的关系

数据结构 作用 底层实现
HashMap 存储键值对 (key-value) 基于哈希表实现
HashSet 存储不重复的元素 底层用 HashMap,元素作为 key

  • HashSet 其实是 HashMap 的“包装”,每个元素作为 HashMap 的 key,value 是固定的占位符。


5. HashSet 如何判断元素唯一?

  • HashSet 调用 HashMap 的 put 方法存元素。

  • HashMap 先计算元素的 hashCode(),定位桶。

  • 桶中遍历已存元素,调用 equals() 判断是否重复。

  • equals() 返回 true 说明元素已存在,不插入。


6. 两个完全一样的元素放入 HashSet 会怎样?

  • 只会存一个,第二个不会插入。

  • 前提是 hashCode()equals() 方法重写正确。

  • 否则可能存入重复元素,失去去重效果。

  • 也就是前面1.说的比较内容时,两个方法要同时重写


7. 两个完全一样的 key-value 放入 HashMap 会怎样?

  • HashMap 中键唯一。

  • 如果两个 key 通过 equals() 相等,第二次 put 遍历之后发现一致会替换旧值。

  • 不会新增键,size() 不变。


8. hashCode 什么时候生成?

  • 调用 hashCode() 方法时即时生成。

  • 对象创建时不生成哈希码。

  • 例如插入 HashMap 时,会调用 hashCode()

  • 部分类如 String 会缓存计算结果,提高效率。


9. 默认的 hashCode() 是怎么实现的?

  • 继承自 Object,通常基于对象的内存地址或 JVM 内部标识生成哈希码。

  • 两个不同对象默认哈希码不同。

  • 如果不重写,逻辑相等的对象哈希码也不同。这也就是为什么重写equals时也要重写hashcode


10. 桶中遍历调用 equals() 的原因

  • 哈希碰撞导致多个元素放在同一桶。

  • 通过遍历桶内元素,调用 equals() 来确认是否重复。

  • 只有 equals() 返回 true,才认定元素相同。


11. 总结

知识点 说明
hashCode 和 equals 关系 equals 相等时,hashCode 必须相等
哈希碰撞 不同对象可能有相同 hashCode,哈希表通过链表或树结构解决冲突
HashMap 唯一键 相同 key 会替换旧值,不新增键
HashSet 唯一元素 通过 HashMap 的 key 唯一性实现去重
hashCode 生成时机 调用时计算,部分类缓存结果
默认 hashCode 基于对象内存地址或 JVM 标识

存档喵~~

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐