JDK 1.8以后,如果链表长度达到8,那就会转为红黑树,时间复杂度会变成O(logn),性能得到大幅度的提升。
putVal方法
节选出遍历链表的一段,如下:
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
//省略
}
treeifyBin方法
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;
do {
TreeNode<K,V> p = replacementTreeNode(e, null);
if (tl == null)
hd = p;
else {
p.prev = tl;
tl.next = p;
}
tl = p;
} while ((e = e.next) != null);
if ((tab[index] = hd) != null)
hd.treeify(tab);
}
}
1)这行代码把链表中某个节点转成了红黑树节点。
TreeNode<K,V> p = replacementTreeNode(e, null);
2)do-while循环这一段,将单向链表转换为了TreeNode类型组成的一个双向链表。
3)这段将双向链表转换为红黑树。
if ((tab[index] = hd) != null)
hd.treeify(tab);
总结
当链表的长度超过8的时候,链表就先是变成双向链表,然后是变成红黑树。