第6题:HashMap的put流程是什么
📚 回答:
-
初始化阶段:
- 调用
HashMap的空参构造时,只会初始化负载因子为0.75,不会创建数组。 - 首次调用
put方法时,才会创建默认容量为16的数组。
- 调用
-
计算位置下标:
- 先计算
key的hashCode值,然后进行二次哈希处理,得到最终的哈希值。 - 哈希值与数组长度减1(
length - 1)进行按位与运算,计算结果即为元素存放的位置下标。
- 先计算
-
插入逻辑:
- 情况1:位置为空
- 如果目标位置没有被占用,直接创建一个
Node节点存入并返回。
- 如果目标位置没有被占用,直接创建一个
- 情况2:位置已被占用(发生哈希冲突)
- 如果该位置是红黑树节点(
TreeNode),则走红黑树的添加或更新逻辑。 - 如果该位置是普通链表节点,则走链表的添加或更新逻辑。
- 树化条件:当链表长度超过8且数组容量 ≥ 64时,链表会转换为红黑树。
- 如果该位置是红黑树节点(
- 情况1:位置为空
-
扩容检查:
- 在返回前,会检查当前数组容量是否超过扩容阈值(
threshold = capacity * loadFactor)。 - 如果超过,则触发扩容操作,新容量为原容量的2倍。
- 在返回前,会检查当前数组容量是否超过扩容阈值(
💡 面试官视角:
- 面试官可能会问“为什么1.8采用尾插法?” 答:相比1.7的头插法,尾插法可以避免在扩容时因链表倒序导致死循环问题,提升了线程安全性。
- 面试官可能会追问“扩容的条件是什么?” 答:在1.7中,只有当容量大于等于阈值且没有空位时才扩容;而在1.8中,只要容量超过阈值就会扩容。
📌 专栏:大白话说Java面试题 — 01-Java基础篇