HashMap (jdk1.8) merge(K key, V value, BiFunction<? super V, ? super V, ? )方法详细注释

merge()方法比compute()多传入一个value参数,根据value参数判断是否新建节点。

merge()方法功能:

如果key存在的情况下:
    value不为空,remappingFunction的apply()执行结果不为空,替换value为apply()执行结果的值;
    value不为空,remappingFunction的apply()执行结果为空,删除key节点;
    value为空:抛出java.lang.NullPointerException异常
   old=查找出的key节点,如果old.value=null,不执行apply,会把value赋值给v,
        再把v赋值给old.value;
key不存在的情况:此时old为空,value不为空,不管remappingFunction的apply()执行完是否为空
    都新建(key,value)节点,此时remappingFunction无效,不执行;

下面看具体注释

/*
    * merge功能:
    * 如果key存在的情况下:
    *       value不为空,remappingFunction的apply()执行结果不为空,替换value为apply()执行结果的值;
    *        value不为空,remappingFunction的apply()执行结果为空,删除key节点;
    *        value为空:抛出java.lang.NullPointerException异常
    *         old=查找出的key节点,如果old.value=null,不执行apply,会把value赋值给v,再把v赋值给old.value;
    * key不存在的情况:此时old为空,value不为空,不管remappingFunction的apply()执行完是否为空
    *       都新建(key,value)节点,此时remappingFunction无效,不执行;

    * */
    @Override
    public V merge(K key, V value,
                   BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        if (value == null) //传入参数value不能为空,否则报空指针
            throw new NullPointerException();
        if (remappingFunction == null)//如果自定义函数为空,抛出异常
            throw new NullPointerException();
        int hash = hash(key);//算出给定key的hash值
        Node<K,V>[] tab; Node<K,V> first; int n, i;
        int binCount = 0;
        HashMap.TreeNode<K,V> t = null;//定义Node类型的数组tab、节点first,n,i;
        Node<K,V> old = null;//定义Node节点old,找到数组或红黑树或链表中和给定的key相同的节点时,赋值给old;
        if (size > threshold || (tab = table) == null ||
                (n = tab.length) == 0)//如果hashMap的长度大于扩容临界值或table及tab的长度为空,
                                      // 则走 resize(),该方法可初始化hashMap,也可以对hashMap进行扩容
            n = (tab = resize()).length;//扩容之后的tab的长度赋值给n;
        if ((first = tab[i = (n - 1) & hash]) != null) {//算出key在tab中的存储位置,如果该位置不为空,把该位置存储的节点赋值给first
                                                         //这种情况key已经存在,返回key对应的value值,可为空可不为空,value为空走,else {v = value; }
                                                        // key不存在时直接判断old是否为空
            if (first instanceof HashMap.TreeNode)//判断first是否红黑树
                old = (t = (HashMap.TreeNode<K,V>)first).getTreeNode(hash, key);//走红黑树分支,找出指定key的赋值给old,t;
            else {//如果不是红黑树,走到这里就是链表
                Node<K,V> e = first; K k;//把first节点赋值给e,定义k;
                do {//通过do-while循环,在链表中找出和给定hash值和key相同的节点,找到之后把链表上的节点e赋值给old,然后推出循环;
                    if (e.hash == hash &&
                            ((k = e.key) == key || (key != null && key.equals(k)))) {
                        old = e;
                        break;
                    }
                    ++binCount;//二叉树计算变量+1;
                } while ((e = e.next) != null);//循环遍历链表上的节点
            }
        }
        if (old != null) { //如果key在tab中不存在,走这里,第一次old肯定为null,old.value也为null,直接到if (value != null)新建节点;
            V v;//定义v;
            if (old.value != null) { //如果old.value不为空,执行自定义函数remappingFunction.apply();
                int mc = modCount;//定义计数变量mc=hashMap结构修改的记录次数modCount
                v = remappingFunction.apply(old.value, value);//调用自定义函数的apply()方法,把执行结果赋值给v;
                if (mc != modCount) {//如果modCount不等于mc,说明有其它线程修改这个hashMap,抛出异常
                    throw new ConcurrentModificationException();
                }
            } else {//如果old.valu为null,走到这里说明key存在,但是key对应的value=null,此时把传入参数value赋值给v;
                v = value;//此时把传入参数value赋值给v;
            }
            if (v != null) { //如果v不为空
                old.value = v; //把v赋值给key对应节点的value;
                afterNodeAccess(old);//回调函数
            }
            else//如果v为空即调用自定义函数的apply()方法,把执行结果为空,则删除key对应的节点;
                removeNode(hash, key, null, false, true);//删除key对应的节点;
            return v;//返回v
        }
        if (value != null) { //如果key在tab中不存在,第一次old肯定为null,old.value也为null,走这个分支;
            if (t != null) //在红黑树中根据指定的key找到一个存储位置,把这个节点赋值为t,如果t不为空;
                t.putTreeVal(this, tab, hash, key, value);//把传入的key和value存入红黑树;
            else {
                tab[i] = newNode(hash, key, value, first);//存入数组tab
                if (binCount >= TREEIFY_THRESHOLD - 1)//如果数组达到二叉树转换的临界值,则把数组tab转化为二叉树
                    treeifyBin(tab, hash);//走二叉树的方法;
            }
            ++modCount;//记录hashMap的修改次数
            ++size;//hashMap的长度加1
            afterNodeInsertion(true);//回调函数
        }
        return value;//value
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值