jdk1.8
final TreeNode<K,V> putTreeVal(HashMap<K,V> map, Node<K,V>[] tab,
int h, K k, V v) {
Class<?> kc = null;
boolean searched = false;
TreeNode<K,V> root = (parent != null) ? root() : this;
for (TreeNode<K,V> p = root;;) {
int dir, ph; K pk;
if ((ph = p.hash) > h)
dir = -1;
else if (ph < h)
dir = 1;
else if ((pk = p.key) == k || (k != null && k.equals(pk)))
return p;
//这个分支我觉得可以替换为下面的代码
//如果使用 comparable 接口还是比较不出大小,那么进入分支
else if ((kc == null && (kc = comparableClassFor(k)) == null) ||
(dir = compareComparables(kc, k, pk)) == 0) {
if (!searched) {
TreeNode<K,V> q, ch;
searched = true;
//这里左右子树都要去找一遍,能找到就返回相同节点
if (((ch = p.left) != null &&
(q = ch.find(h, k, kc)) != null) ||
((ch = p.right) != null &&
(q = ch.find(h, k, kc)) != null))
return q;
}
dir = tieBreakOrder(k, pk);
}
TreeNode<K,V> xp = p;
if ((p = (dir <= 0) ? p.left : p.right) == null) {
Node<K,V> xpn = xp.next;
TreeNode<K,V> x = map.newTreeNode(h, k, v, xpn);
if (dir <= 0)
xp.left = x;
else
xp.right = x;
xp.next = x;
x.parent = x.prev = xp;
if (xpn != null)
((TreeNode<K,V>)xpn).prev = x;
moveRootToFront(tab, balanceInsertion(root, x));
return null;
}
}
}
我觉得上面这个分支可以替换为下面的代码
else if ((kc == null && (kc = comparableClassFor(k)) == null) ||
(dir = compareComparables(kc, k, pk)) == 0) {
dir = tieBreakOrder(k, pk);
}
因为 tieBreakOrder 就是当实在比较不出大小时,用来给一种默认的顺序(默认的顺序是新插入的节点更小,可以从调用 tieBreakOrder 的实参顺序 tieBreakOrder(k, pk)看出来,treeify 函数里也是这个实参顺序)。那既然,即使分不出大小也有默认顺序,那么就按照顺序走二叉查找的过程不就得了,把判断相等的任务全权交给else if ((pk = p.key) == k || (k != null && k.equals(pk)))
不就好了吗?
emmmmm。。。我写到这里好像想到答案了,,,难道是因为还有那些左旋右旋操作,所以这种默认顺序可能被破坏呗。但这好像也不对,那既然默认顺序会被破坏,那么你现在按照dir = tieBreakOrder(k, pk);
(这句肯定会被执行,当分不出大小时)的方向往下走,那岂不是也可能不对了吗?
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.