int d;
if (a == null || b == null ||
(d = a.getClass().getName().
compareTo(b.getClass().getName())) == 0)
d = (System.identityHashCode(a) <= System.identityHashCode(b) ?
-1 : 1);
return d;
}
这个方法是确定插入顺序的 先比较类名的排名 然后比较对象哈希值的排名 System类的那个方法和hashCode方法返回值是一样的
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) {
x.parent = null;
x.red = false;
root = x;
}
else {
K k = x.key;
int h = x.hash;
Class<?> kc = null;
for (TreeNode<K,V> p = root;;) {
int dir, ph;
K pk = p.key;
if ((ph = p.hash) > h)
dir = -1;
else if (ph < h)
dir = 1;
else if ((kc == null &&
(kc = comparableClassFor(k)) == null) ||
(dir = compareComparables(kc, k, pk)) == 0)
dir = tieBreakOrder(k, pk);
TreeNode<K,V> xp = p;
if ((p = (dir <= 0) ? p.left : p.right) == null) {
x.parent = xp;
if (dir <= 0)
xp.left = x;
else
xp.right = x;
root = balanceInsertion(root, x);
break;
}
}
}
}
moveRootToFront(tab, root);
}
这个方法是将链表转换成树的方法
首先定义根节点root
进入for循环 创建x变量 初始值为本树节点对象 再定义next对象 循环条件是x不为空 x赋next的引用
next赋引用为x的next节点
x的左和右节点都置空
判断如果root为空 说明是第一次遍历 将x的父节点置空 x置为黑树 将x设为root
如果根节点不为空
将x的键赋给变量k 将x的哈希值赋给临时变量h 定义Class类型kc用来判断节点的类
再进入一个无限的for循环 从root开始遍历
定义临时变量dir 和 ph
将p的键赋给临时变量pk
将p的哈希值赋给ph 判断ph是否大于h 也就是x的哈希值 dir返回-1 如果小于就返回1 如果等于 就判断如果kc为空也就是第一次循环 且x的键的类型不是Comparable实现类或p的键和x的键比值一样 调用上面那个方法确定dir
将p赋给临时变量xp
判断如果dir小于等于0且p的左节点为空 或 dir大于0且p的右节点为空
将x的父节点设为p 将x赋给p的左节点或右节点 根据dir值
然后调用balanceInsertion方法调整root 然后跳出循环
这个嵌套的for循环 其实就是判断出来当前节点不是根节点 就给当前节点找父节点 并确定当前节点是父节点的左还是右节点
跳出所有的循环后 将根节点移动到哈希桶数组中
final Node<K,V> untreeify(HashMap<K,V> map) {
Node<K,V> hd = null, tl = null;
for (Node<K,V> q = this; q != null; q = q.next) {
Node<K,V> p = map.replacementNode(q, null);
if (tl == null)
hd = p;
else
tl.next = p;
tl = p;
}
return hd;
}
这个方法是将树降级成链表的方法 不多说了 就是循环遍历树节点 将每个树节点向上转型成普通节点 挨个穿成链表 最后返回首节点