面试题答案
一键面试键值对存储
- HashMap:
- 基于哈希表实现,使用数组(桶)和链表(JDK 1.7 及之前)或红黑树(JDK 1.8 及之后)组合的数据结构。通过对键的哈希值进行计算,确定键值对在数组中的存储位置。
- 当哈希冲突发生时(不同键计算出相同的哈希值),JDK 1.7 及之前采用链表将冲突的键值对链接起来;JDK 1.8 及之后,当链表长度超过阈值(默认为 8)时,链表会转换为红黑树,以提高查找性能。
- TreeMap:
- 基于红黑树实现,红黑树是一种自平衡的二叉搜索树。每个节点包含键值对,按照键的自然顺序(实现
Comparable
接口)或自定义比较器(传入Comparator
)的顺序进行存储。
- 基于红黑树实现,红黑树是一种自平衡的二叉搜索树。每个节点包含键值对,按照键的自然顺序(实现
排序
- HashMap:
- 没有对键值对进行排序,其遍历顺序是不确定的,只保证相同哈希值的键值对在冲突链(链表或红黑树)中的相对顺序。
- TreeMap:
- 按照键的顺序对键值对进行排序。可以是键的自然顺序(如果键实现了
Comparable
接口),也可以通过构造函数传入Comparator
来指定排序规则。
- 按照键的顺序对键值对进行排序。可以是键的自然顺序(如果键实现了
性能优化
- HashMap:
- 插入性能:在理想情况下(哈希分布均匀,无冲突),插入操作的时间复杂度接近 O(1)。但在哈希冲突严重时,时间复杂度会退化为 O(n),不过 JDK 1.8 引入红黑树优化了这种情况,当链表长度过长转换为红黑树后,插入操作时间复杂度为 O(log n)。
- 查找性能:与插入类似,理想情况下时间复杂度为 O(1),冲突严重时,链表结构下为 O(n),红黑树结构下为 O(log n)。
- 扩容机制:当哈希表中元素数量达到负载因子(默认为 0.75)与容量的乘积时,会进行扩容。扩容时会重新计算键的哈希值并重新分配到新的数组位置,这一过程比较耗时,所以尽量在初始化时预估好数据量,减少扩容次数。
- TreeMap:
- 插入性能:由于红黑树需要维持平衡,插入操作时间复杂度为 O(log n),相比理想情况下的 HashMap 插入性能略低。
- 查找性能:查找操作时间复杂度为 O(log n),同样由于红黑树的平衡特性,查找性能相对稳定,不受数据分布影响。
- 无需扩容:因为红黑树结构的灵活性,TreeMap 不需要像 HashMap 那样进行扩容操作。