HashMap (jdk1.8)put()方法详细注释

 HashMap1.8中的put方法直接调用 putVal()方法,所以本文主要注释了 putVal()方法里面的代码。

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i; //定义存放元素的节点数组,节点,变量n,i;
        if ((tab = table) == null || (n = tab.length) == 0) //把成员变量table赋值给tab,如果table、tab为空,把tab初始化,长度n为初始化后数组的默认长度16
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null) //当前节点存放在数组中,没有存放到红黑树和链表中,n-1=15,(n - 1) & hash能得到数组的下标位置,如果tab[i]==null,说明这个位置可以存放元素p
            tab[i] = newNode(hash, key, value, null);  //在tab[i]处新建节点存放元素(hash, key, value, null)
        else {  //tab[i]已经有存放的元素,说明hash冲突
            Node<K,V> e; K k;  //定义一个节点数组e和K k值;
            /*
            * 如果当前节点的hash值(p.hash)和参数列表中的hash值相等且当前节点的key和给定的key相等,则把当前节点赋值给e;
            * */
            if (p.hash == hash &&
                    ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof HashMap.TreeNode)  //如果当前节点是红黑树,则走红黑树的分支
                e = ((HashMap.TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {    //当前节点是链表的情况,通过for循环遍历链表中的元素,把链表中的元素存放到map中,for()没有循环终止条件,只能在程序中break
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) { //如果当前节点指向的next为空,说明链表上之后一个元素,这个元素又在数组上存储,可以把这个元素存储到next节点
                        p.next = newNode(hash, key, value, null); //在链表的next的节点新建一个node,存储给定的值(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st 如果链表上节点数量超过二叉树临界点的值,链表转换为二叉树
                            treeifyBin(tab, hash);
                        break;                                 //退出if(e = p.next) == null)
                    }
                    if (e.hash == hash &&
                            ((k = e.key) == key || (key != null && key.equals(k)))) //如果next位置的元素和给定的元素是同一个值,则退出,把当前元素赋值给当前元素
                        break;  //退出
                    p = e;
                }
            }
            /*
            * e中存储的是hash值和key值都和给定元素相同的节点:
            * 参考【if (p.hash == hash &&
                    ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            *     if (e.hash == hash &&
                            ((k = e.key) == key || (key != null && key.equals(k)))) //如果next位置的元素和给定的元素是同一个值,则退出,把当前元素赋值给当前元素
                        break;  //退出
                    p = e;】
                    * 此时需要根据 onlyIfAbsent来确定是否替换value
                    *onlyIfAbsent:如果当前位置已存在一个值,是否替换,false是替换,true是不替换
                    *
            * */
            if (e != null) { // existing mapping for key
                V oldValue = e.value; //把e节点的值赋值给oldValue
                if (!onlyIfAbsent || oldValue == null) //根据条件判断是否替换
                    e.value = value; //替换
                afterNodeAccess(e); //回调函数,把e节点移动到map最后
                return oldValue; //不替换返回之前的值
            }
        }
        ++modCount;    //记录HashMap被结构修改的次数
        if (++size > threshold)  //map长度大于扩容临界值,map扩容
            resize(); //扩容方法
        afterNodeInsertion(evict); //回调函数,新节点插入之后回调 , 根据evict 和   判断是否需要删除最老插入的节点。
        return null; //返回
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值