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;
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;
}
}
}
这个方法是插入树节点的方法
首先定义Class类型临时变量kc 布尔临时变量searched默认为false
然后创建root变量获取根节点 就是判断本节点的父节点是否为空 如果父节点不为空 就调用root方法获取 如果父节点为空 本节点就作为根节点
然后进入for循环遍历每个节点 循环变量是p 初始值是root
创建临时变量dir ph和pk
将p的哈希值赋给ph 判断ph如果大于参数h dir就是-1
如果ph小于参数h dir就是1 就是判断传进来的参数的哈希值和这里遍历的节点的哈希值 用来确定传进来的参数添加到节点的哪里
如果传进来的k键和遍历中的节点的键一致或为同一对象 那么直接返回该节点
如果两个哈希值相同 kc为空 且 参数键k的类型不是Comparable 或参数k和本节点的键相比的比值为0 那么判断searched变量是否为false 也就是没进行过搜索 将search变量设为true 就对p的左子树和右子树进行搜索 搜到了和要插入的节点相同的节点 就返回搜到的节点 最后跳出判断searched变量后 调用tieBreakOrder给dir赋值
然后根据dir的值判断 如果dir小于等于0 且p的左节点为空 或dir大于0 且p的右节点为空
那么将p的下一个节点设置为树节点 通过调用参数map的newTreeNode方法 将新传入的键值对放在本节点和下一个节点之间的节点 操作方式就是本节点的下一个节点作为新节点的下一个节点 新节点根据dir值放在本节点的左子树或右子树中 新节点作为本节点的下一个节点 新节点的上一个节点和父节点都变成成本节点 新节点的下一个节点(曾是本节点的下一个节点)的上一个节点设为新节点
然后将根节点移动到哈希桶数组中 并调用balanceInsertion方法调整根节点
最后返回空值
search变量设为true
final void removeTreeNode(HashMap<K,V> map, Node<K,V>[] tab,
boolean movable) {
int n;
if (tab == null || (n = tab.length) == 0)
return;
int index = (n - 1) & hash;
TreeNode<K,V> first = (TreeNode<K,V>)tab[index], root = first, rl;
TreeNode<K,V> succ = (TreeNode<K,V>)next, pred = prev;
if (pred == null)
tab[index] = first = succ;
else
pred.next = succ;
if (succ != null)
succ.prev = pred;
if (first == null)
return;
if (root.parent != null)
root = root.root();
if (root == null || root.right == null ||
(rl = root.left) == null || rl.left == null) {
tab[index] = first.untreeify(map); // too small
return;
}
TreeNode<K,V> p = this, pl = left, pr = right, replacement;
if (pl != null && pr != null) {
TreeNode<K,V> s = pr, sl;
while ((sl = s.left) != null) // find successor
s = sl;
boolean c = s.red; s.red = p.red; p.red = c; // swap colors
TreeNode<K,V> sr = s.right;
TreeNode<K,V> pp = p.parent;
if (s == pr) { // p was s's direct parent
p.parent = s;
s.right = p;
}
else {
TreeNode<K,V> sp = s.parent;
if ((p.parent = sp) != null) {
if (s == sp.left)
sp.left = p;
else
sp.right = p;
}
if ((s.right = pr) != null)
pr.parent = s;
}
p.left = null;
if ((p.right = sr) != null)
sr.parent = p;
if ((s.left = pl) != null)
pl.parent = s;
if ((s.parent = pp) == null)
root = s;
else if (p == pp.left)
pp.left = s;
else
pp.right = s;
if (sr != null)
replacement = sr;
else
replacement = p;
}
else if (pl != null)
replacement = pl;
else if (pr != null)
replacement = pr;
else
replacement = p;
if (replacement != p) {
TreeNode<K,V> pp = replacement.parent = p.parent;
if (pp == null)
root = replacement;
else if (p == pp.left)
pp.left = replacement;
else
pp.right = replacement;
p.left = p.right = p.parent = null;
}
TreeNode<K,V> r = p.red ? root : balanceDeletion(root, replacement);
if (replacement == p) { // detach
TreeNode<K,V> pp = p.parent;
p.parent = null;
if (pp != null) {
if (p == pp.left)
pp.left = null;
else if (p == pp.right)
pp.right = null;
}
}
if (movable)
moveRootToFront(tab, r);
}
这个方法是删除树节点的方法
先判断哈希桶数组是否为空 如果为空或没有元素 就直接返回
然后根据传进来的哈希值确定是在哪个桶 用哈希桶数组长度减一 再按位与哈希值的方法计算得出
创建临时变量first 赋为哈希桶数组指定下标的元素 也就是整棵树的根节点 root也赋为这个根节点 再创建一个rl变量 默认为空
创建临时变量succ 赋为next节点 创建临时变量pred 赋为prev节点
判断如果pred为空 也就是前驱节点为空 那么哈希桶数组的下标元素和first元素赋为succ 也就是说要删除的是第一个元素 那么其他元素前移
如果pred不为空 那么pred和succ直接建立关联 pred的next属性为succ succ的prev属性为pred
如果first还是为空 那么说明树为空树 直接返回
如果root节点的父节点不为空 那么调用root方法重新赋给root
如果root为空或root的右子树为空 或root的左子树为空 或root的左子树的左子树为空 那么调用untreeify方法将树变成链表 然后返回
然后创建临时变量p引用本节点 pl引用左节点 pr引用右节点 replcement为临时创建的变量
如果pl和pr都不为空
进入while循环 创建临时变量s 引用pr 不断判断s的左子树以及左子树的左子树 直到找到一个左子树为空的节点 也就是用右子树的左子树的左子树。。。的左子树 直到一个左子树的左子树为空时 再跳出循环
然后再将这个s的红与黑属性和本节点的红与黑属性替换
创建临时变量sr 赋为s的右子树 创建临时变量pp 赋为p的父元素
判断如果选出来的s是pr 也就是s是本节点的直接右子树 (这个直接的右子树的左子树为空) 那么将s和p互换 s成为本节点p的父节点 s的右子树为p
如果s不是p的直接右子树
创建临时变量sp 赋为s的直接父元素
将sp赋给p的parent 也就是将sp变成p的父元素 判断sp不为空的话 再判断如果s是sp的左子树 那么p就变成sp的左子树 如果s是sp的右子树 那么p就变成sp的右子树 换句话说 如果s不是p的直接右子树 那么p直接替换s
然后s的右子树变为pr 就是p的右子树给了s
此时p的移位暂告一段落 p要么是s的右子树 也就是p是自己右子树的右子树 p要么是p的某个右子树的左子树的左子树。。。的左子树
然后将p的左子树置空
然后将s的右子树变成p的右子树
然后将p的左子树变成s的左子树
然后用s将p替换 s的父节变成p的父节点 如果p本身是个左节点 那么s就替代成为这个左节点 如果p是个右节点 那么s就替代成为这个右节点
判断s的右子树是否为空 如果不为空 replacement赋为s的右子树sr 否则replacement就是p
pl不为空 pr为空的情况 pl就是replacement pr不为空 pl为了的情况pr就是replacement 都为空p就是replacement
如果replacement不是p 那么就将replacement替代p p置空
创建临时变量r 判断如果p是红色 r就是root p是黑色r就是balanceDeletion的返回值
如果replacement是p 那么直接置空p 因为p可能是链条的最末端 没了就没了
如果movable为true 就将r换到哈希桶数组下表那里 就是变成root元素
这个方法看起来很复杂 其实就是条件判断多了些 逻辑就是删了本节点 要找本节点的替代品
如果本节点左子树为空 那么替代本节点的就是右子树 如果右子树为空 那么替代本节点的就是左子树 如果都为空 那么本节点直接取消
大致流程图如下