HashMap源码详细分析(下)

HashMap

remove方法总体来说就是找到对应的key,如果是链表结构就删除链表节点,如果是红黑树节点就删除红黑树节点,下面对remove方法的过程进行了详细的备注,关于红黑树deleteBalance图解参考:
https://blog.csdn.net/qq_40753996/article/details/89814273

remove方法

public V remove(Object key) {
    Node<K,V> e;
//false位置参数:是否匹配值
    return (e = removeNode(hash(key), key, null, false, true)) == null ?
        null : e.value;
}

removeNode方法

final Node<K,V> removeNode(int hash, Object key, Object value,
                           boolean matchValue, boolean movable) {
//tab:hash表 
//p:key映射在hash表上的头节点 
    Node<K,V>[] tab; Node<K,V> p; int n, index;
//指定位置非空
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (p = tab[index = (n - 1) & hash]) != null) {
//查找要移除的节点
//node:要移除的节点
        Node<K,V> node = null, e; K k; V v;
//头节点即为要查找的节点
        if (p.hash == hash &&
            ((k = p.key) == key || (key != null && key.equals(k))))
            node = p;
        else if ((e = p.next) != null) {
//树中查找
            if (p instanceof TreeNode)
                node = ((TreeNode<K,V>)p).getTreeNode(hash, key);
            else {
//链表中查找
                do {
                    if (e.hash == hash &&
                        ((k = e.key) == key ||
                         (key != null && key.equals(k)))) {
                        node = e;
                        break;
                    }
                    p = e;
                } while ((e = e.next) != null);
            }
        }
//matchValue 默认为false,
        if (node != null && (!matchValue || (v = node.value) == value ||
                             (value != null && value.equals(v)))) {
//树中移除node
            if (node instanceof TreeNode)
                ((TreeNode<K,V>)node).removeTreeNode(this, tab, movable);
//头节点移除
            else if (node == p)
                tab[index] = node.next;
            else
//链表移除,p指向移除节点的前一个
                p.next = node.next;
            ++modCount;
            --size;
            afterNodeRemoval(node);
            return node;
        }
    }
    return null;
}

RemoveTreeNode

源码流程图:
在这里插入图片描述

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;
//删除节点,子节点replacement 代替删除节点的位置
//replacement :删除节点的子节点
    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);
}

balanceDeletion

源码流程图:
在这里插入图片描述

static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,
                                           TreeNode<K,V> x) {
//xpl、xpr声明为S
    for (TreeNode<K,V> xp, xpl, xpr;;)  {
	//x为根
        if (x == null || x == root)
            return root;
	//x为根
        else if ((xp = x.parent) == null) {
            x.red = false;
            return x;
        }
	//x为红色变黑结束
        else if (x.red) {
            x.red = false;
            return root;
        }
	//xpl、xpr声明为S
	//x为左子树
        else if ((xpl = xp.left) == x) {
	   //兄弟S为红色,左旋,更新S
            if ((xpr = xp.right) != null && xpr.red) {
                xpr.red = false;
                xp.red = true;
                root = rotateLeft(root, xp);
                xpr = (xp = x.parent) == null ? null : xp.right;
            }
	   //S为空,结束
            if (xpr == null)
                x = xp;
            else {
//xpl、xpr声明为S
                TreeNode<K,V> sl = xpr.left, sr = xpr.right;
		//S、SR、SL都黑,S变红,x=p,进入下一个循环,平衡x(空算黑)
                if ((sr == null || !sr.red) &&
                    (sl == null || !sl.red)) {
                    xpr.red = true;
                    x = xp;
                }
                else {
		    //1.SR为黑(空算黑),右旋S,更新S、SR、SL
                    if (sr == null || !sr.red) {
                        if (sl != null)
                            sl.red = false;
                        xpr.red = true;
                        root = rotateRight(root, xpr);
                        xpr = (xp = x.parent) == null ?
                            null : xp.right;
                    }
	   //2.更新S、SR、SL,SR变黑
                    if (xpr != null) {
                        xpr.red = (xp == null) ? false : xp.red;
                        if ((sr = xpr.right) != null)
                            sr.red = false;
                    }
	    //3.左旋P
                    if (xp != null) {
                        xp.red = false;
                        root = rotateLeft(root, xp);
                    }
	     //结束
                    x = root;
                }
            }
        }//x为右子树
        else { // symmetric
//兄弟S为红色,右旋,更新S
            if (xpl != null && xpl.red) {
                xpl.red = false;
                xp.red = true;
                root = rotateRight(root, xp);
                xpl = (xp = x.parent) == null ? null : xp.left;
            }
//S为空,结束
            if (xpl == null)
                x = xp;
            else {
                TreeNode<K,V> sl = xpl.left, sr = xpl.right;
	//S、SR、SL都黑,S变红,x=p,进入下一个循环,平衡x(空算黑)
                if ((sl == null || !sl.red) &&
                    (sr == null || !sr.red)) {
                    xpl.red = true;
                    x = xp;
                }
                else {
	    //1.SL为黑(空算黑),左旋S
                    if (sl == null || !sl.red) {
                        if (sr != null)
                            sr.red = false;
                        xpl.red = true;
                        root = rotateLeft(root, xpl);
                        xpl = (xp = x.parent) == null ?
                            null : xp.left;
                    }
	    //2.更新S、SR、SL,SL变黑
                    if (xpl != null) {
                        xpl.red = (xp == null) ? false : xp.red;
                        if ((sl = xpl.left) != null)
                            sl.red = false;
                    }
	    //3.右旋P
                    if (xp != null) {
                        xp.red = false;
                        root = rotateRight(root, xp);
                    }
//结束
                    x = root;
                }
            }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值