说明看注释
一、treeifyBin方法
final void treeifyBin(Node<K, V>[] tab, int hash) {
//n 数组的长度,index 数组位置
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) {
//当当前找的节点e不为空
//hd红黑树链表头,红黑树链表尾(红黑树中不仅有维护其所有节点的红黑树结构,还有所有节点的链表结构)
//所以先将目前节点按链表排列好,在进行红黑树化
TreeNode<K, V> hd = null, tl = null;
//遍历列表
do {
//将当前e节点装化为TreeNode
TreeNode<K, V> p = replacementTreeNode(e, null);
//如果tl不存在
if (tl == null) {
//则p为hd
hd = p;
} else {
//若存在则p的前节点指向tl
p.prev = tl;
//tl的后节点指向p
tl.next = p;
}
//最后将tl指向p
tl = p;
} while ((e = e.next) != null);
if ((tab[index] = hd) != null) {
//将hd放在数组上,且hd存在,将链表进行红黑树化
hd.treeify(tab);
}
}
}
二、treeify方法
final void treeify(Node<K, V>[] tab) {
TreeNode<K, V> root = null;
for (TreeNode<K, V> x = this, next; x != null; x = next) {
//根据链表进行遍历
next = (TreeNode<K, V>) x.next;
x.left = x.right = null;
if (root == null) {
//如果根节点还没设置则当前节点设置为根节点root
x.parent = null;
//根节点一定是黑色的
x.red = false;
root = x;
} else {
//获取当前循环节点的key和哈希值
K k = x.key;
int h = x.hash;
Class<?> kc = null;
//每次都从根节点开始循环
TreeNode<K, V> p = root;
for (; ; ) {
//遍历当前红黑树
int dir;
//获得p的hash值和key
int ph = p.hash;
K pk = p.key;
//比较hash值,然后根据比较值dir决定插入左边还是右边
if (ph > h) {
dir = -1;
} else if (ph < h) {
dir = 1;
} else if ((kc == null && (kc = comparableClassFor(k)) == null) ||
(dir = compareComparables(kc, k, pk)) == 0) {
//k不是不是课比较类或者比较结果为0,使用tieBreakOrder方法比较
dir = tieBreakOrder(k, pk);
}
TreeNode<K, V> xp = p;
p = (dir <= 0) ? p.left : p.right;
//仅当当前要插入的位置上没有节点时才进行插入,否则继续向下遍历
if (p == null) {
//设置父节点
x.parent = xp;
//根据dir值设置为父节点的左右子节点
if (dir <= 0) {
xp.left = x;
} else {
xp.right = x;
}
//插入成功后平衡红黑树
root = balanceInsertion(root, x);
//跳出当前循环
break;
}
}
}
}
//确保当前的root是直接落在table数组上的
moveRootToFront(tab, root);
}