面试题答案
一键面试1. HashMap的扩容机制
- 扩容条件:当HashMap中的元素数量(size)达到阈值(threshold)时就会触发扩容。阈值的计算公式为
threshold = capacity * loadFactor
。在初始化容量为16,加载因子为0.75的情况下,阈值为16 * 0.75 = 12
。即当元素数量达到12时,就会触发扩容。 - 扩容过程:
- 创建新数组:扩容时会创建一个新的数组,新数组的容量是原数组容量的2倍。例如原容量为16,扩容后变为32。
- 重新计算哈希值和位置:将原数组中的所有键值对重新计算哈希值,并根据新的容量重新确定在新数组中的位置,然后复制到新数组中。这是因为容量改变后,哈希值与数组位置的映射关系也会改变。具体来说,计算位置的公式为
index = hash & (newCapacity - 1)
。扩容时重新计算哈希值,能让元素在新数组中分布更均匀,减少哈希冲突。
2. 不同初始化参数对性能的影响
- 容量:
- 容量过小:如果初始容量设置过小,会导致频繁扩容。每次扩容都需要重新计算哈希值和复制数据,这会带来较大的性能开销,降低插入和查找操作的效率。例如,初始容量为4,加载因子0.75,阈值为3,数据量稍大就会频繁扩容。
- 容量过大:如果初始容量设置过大,会浪费内存空间,因为HashMap数组中很多位置可能一直为空。虽然减少了扩容次数,但由于数组占用空间大,也会影响整体性能。
- 加载因子:
- 加载因子过小:加载因子越小,触发扩容的阈值越低,会导致扩容频繁。例如加载因子设为0.5,初始容量16,阈值为8,相比加载因子0.75会更早触发扩容,同样会增加性能开销。
- 加载因子过大:加载因子越大,触发扩容的阈值越高,扩容次数减少。但这会导致哈希冲突增多,因为元素在数组中的分布更密集,查找操作的时间复杂度会增加,降低查找性能。
3. 调整初始化参数避免不必要的性能损耗
- 预估数据量:在使用HashMap前,尽量预估数据量的大小。如果能大致知道数据量,可根据公式
capacity = (预估数据量 / loadFactor) + 1
来设置初始容量,尽量减少扩容次数。例如,预估数据量为100,加载因子0.75,那么初始容量设置为(100 / 0.75) + 1 ≈ 134
,实际设置时可选择大于134的2的幂次方,如128的下一个2的幂次方256。 - 选择合适加载因子:根据实际应用场景选择加载因子。如果对空间比较敏感,可适当提高加载因子(但不能过大,避免哈希冲突严重影响性能);如果对查询性能要求较高,可适当降低加载因子,以减少哈希冲突。一般情况下,默认的加载因子0.75是一个比较平衡的选择,兼顾了空间和时间性能。