HashMap (jdk1.8)compute()方法注释

computeIfAbsent 是实现Map接口中的方法,功能如:

 /*
    * compute功能:给定的key在hashMap中存在时,如果remappingFunction的apply()执行结果为null,
    * 则删除节点,不为null,则用apply()执行结果的值替换当前key的value;
    * 如果给定的key在hashMap中不存在时,如果remappingFunction的apply()执行结果为null,直接return v,此时v=null;
    * 如果remappingFunction的apply()执行结果不为null,则增加新节点(hash, key, v, first);
    * */

@Override
    public V compute(K key,
                     BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        if (remappingFunction == null)//如果自定义函数为空,抛出异常
            throw new NullPointerException();
        int hash = hash(key);//算出给定key的hash值
        Node<K,V>[] tab; Node<K,V> first; int n, i;//定义Node类型的数组tab、节点first,n,i;
        int binCount = 0;//定义二叉树的计数变量;
        HashMap.TreeNode<K,V> t = null;//定义红黑树节点t;
        Node<K,V> old = null;//定义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值oldValue,key不存在时直接走
                                                            // V oldValue = (old == null) ? null : old.value;int mc = modCount;及后面的内容,
            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);//循环遍历链表上的节点
            }
        }
        V oldValue = (old == null) ? null : old.value;//定义V类型变量:oldValue,它的值等于old.value,如果old为空,oldValue=null;
        int mc = modCount;//定义计数变量mc=hashMap结构修改的记录次数modCount
        V v = remappingFunction.apply(key, oldValue);//调用自定义函数的apply()方法,该方法能获取key对应的value,赋值给v;
        if (mc != modCount) { throw new ConcurrentModificationException(); }//如果modCount不等于mc,说明有其它线程修改这个hashMap,抛出异常
        if (old != null) {//根据key查到节点old不为空
            if (v != null) {//apply执行结果不为null;
                old.value = v;//用apply执行结果的值覆盖key对应的value;
                afterNodeAccess(old);//回调函数
            }
            else//如果apply执行结果为null,则删除对应的key节点,此时key对应的value为空
                removeNode(hash, key, null, false, true);
        }
        else if (v != null) { //如果old存在,v不为空,找到的红黑树t不为空,把节点存储到红黑树上
            if (t != null)
                t.putTreeVal(this, tab, hash, key, v);
            else { //走到这里说明时新节点可以存储到数组上,直接新建node(hash, key, v, first);
                tab[i] = newNode(hash, key, v, first);
                if (binCount >= TREEIFY_THRESHOLD - 1) //如果满足二叉树条件,新建节点存入二叉树
                    treeifyBin(tab, hash);
            }
            modCount = mc + 1;//记录hashMap的修改次数
            ++size;//hashMap的长度加1
            afterNodeInsertion(true);//回调函数
        }
        return v;//返回v
    }

上一篇:触发器


下一篇:算法题里一些集合类常用的定义与方法(自用)