那扩容机制了解吗?

HashMap是通过数组+链表和红黑树的组合实现的。在HashMap中,用于存放key值的桶数组的长度是固定的,由初始化参数确定。

随着数据的插入数量增加和负载因子的作用,可能需要对HashMap进行扩容以容纳更多的数据。在扩容过程中,JDK 1.8引入了一项优化操作,可以避免重新计算每个元素的哈希值。

由于HashMap的初始容量是2的幂次,扩容后的长度是原来的两倍,新的容量也是2的幂次。因此,元素要么保持在原位置,要么移动到原位置再加上旧容量的位置。

可以看下面这张图,其中n表示table的长度。图中的"a"表示扩容前的key1和key2两个键确定的索引位置,图中的"b"表示扩容后key1和key2两个键确定的索引位置。

1.png

元素在重新计算哈希之后,由于n变为原来的两倍,n-1的掩码范围在高位多了1位(红色)。因此,新的索引位置会发生变化:

2.png

在扩容时,只需要观察原哈希值新增的那一位是0还是1。如果是0,索引位置保持不变;如果是1,索引位置变为"原索引位置 + 旧容量"。

扩容节点迁移主要逻辑:

3.png

标签: java, Java面试题, Java问题合集, Java编程, Java问题精选, Java常见问题