HashMap底层原理与扩容机制

发布时间 2023-11-30 17:18:57作者: adam.li


1.7 数组 + 链表
1.8 数组 + (链表 | 红黑树)

JAVA 1.8 之后hashmap 树化规则

HashMap里面定义了一个常量TREEIFY_THRESHOLD = 8,当链表长度超过树化阈值 8 时,
先尝试调用resize()方法进行扩容来减少链表长度,如果数组容量已经 >=64(MIN_TREEIFY_CAPACITY),
才会进行树化,Node节点转为TreeNode节点(TreeNode也是HashMap中定义的内部类)。
如下代码所示:在计算当前key时候,遍历当前桶 节点Node数binCount,如果binCount大于TREEIFY_THRESHOLD 8,则调用treeifyBin 尝试扩容。
treeifyBin 方法中 如果桶数组长度tab.length小于MIN_TREEIFY_CAPACITY 64,则直接桶数组扩容;
如果 桶数组长度tab.length大于MIN_TREEIFY_CAPACITY 64 则Node节点转为TreeNode(红黑树)节点
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
...
int binCount = 0;
if ((first = tab[i = (n - 1) & hash]) != null) {
if (first instanceof TreeNode)
old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key);
else {
Node<K,V> e = first; K k;
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
old = e;
break;
}
++binCount;
} while ((e = e.next) != null);
}
}
...
tab[i] = newNode(hash, key, v, first);
if (binCount >= TREEIFY_THRESHOLD - 1)
treeifyBin(tab, hash);
}

final void treeifyBin(Node<K,V>[] tab, int hash) {
int n, index; Node<K,V> e;
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
resize();
else if ((e = tab[index = (n - 1) & hash]) != null) {
TreeNode<K,V> hd = null, tl = null;
}