HashMap

put方法(当put第2^30*0.75+1时,则threshold = 2^31,返回旧的2^30的数组。之后不在扩容,直到put到满数组)

        a:第一次put值时。(第一个扩容)先创建大小为16的Node类型数组table,threshold为12。后算出p=table[(16-1)& hash],如果p==null,则创建一个Node对象直接放入table[(16-1)& hash]。

        b:如果p!=null时。则判断第二次put的key与p.key相同,则p.value=第二次put的value。

        c:如果p!=null,p的节点为TreeNode时。则putTreeVal()。

        d:如果p!=null,其他情况时(发生hash冲突)。循环p节点的链:1、p.next==null,则向p.next插入创建的Node(当该链有7个+包括数组上的节点=8时,且数组的容量>=64时,在向该链put时,该链变树)。2、p.next!=null,p.key与put的key相同。则则p.value=put的value。

        e:(第二次扩容)当table的大小变为13时:第一步:threshold变为oldThreshold<<1=24,table的大小变为newCap = oldCap<<1=32。第二步:循环老的数组oldTab(大小为16),递增变量为j,oldTab[j]为null则不任何操作,否则(1.判断oldTab[j].next==null,则计算index=oldTab[j].hash & 31,放入新的大小为32的数组。2.判断oldTab[j]为TreeNode,则oldTab[j].split。3.根据条件oldTab[j].hash & oldCap ==0意思为oldTab[j].hash的二进制的第5位等于0,将满足条件的Node组成一个低链,放在newTab[j]上,将不满足条件的Node组成一个高链,放在newTab[j+oldCap])。

//双参构造 
public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        this.loadFactor = loadFactor;
        // threshhold为大于initialCapacity值,2的n次方值
        // 例如initialCapacity=10,或11,或12。threshold=2^4=16
        //  initialCapacity=10000。threshold=2^14=16384
        //  在调用put时,会发生扩容:newCap=threshold,newThr=newCap*loadFactor
        this.threshold = tableSizeFor(initialCapacity);
}

// HashMap的默认构造方法中,初始化loadFactor=0.75
// 属性 DEFAULT_INITIAL_CAPACITY = 1 << 4 =16;1X2^4;
V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
    //临时变量
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    
    // 第一次put值时
    if ((tab = table) == null || (n = tab.length) == 0)
            //第一个扩容时,threshold=0变为16*0.75=12
            // Node<K,V>[] resize()->{
            //                //new一个大小为16的Node类型的数组,返回
            //                Node<K,V>[] table = (Node<K,V>[])new Node[newCap]; 
            //                retrun table;         
            //             }
            // n=12
            n = (tab = resize()).length;
    
    // 计算tab数组的index。如果tab[index]==null,就new    
    // hash=key.hashCode() ^ key.hashCode()>>> 16
    if ((p = tab[i = (n - 1) & hash]) == null)
            //用Node类的全参构造创建一个对象,
            tab[i] = newNode(hash, key, value, null);
    else{
        //tab[index]不为null,说明之前put过,p = tab [index];
        //之前key的hash是否与当前put的key的hash是否相等  &&
        // ( 之前的key 是否等于 当前的key || (当前key不为null && 当前key等与之前的key))
        if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
        // 该节点是否为TreeNode节点
        else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else{
            // 死循环,记录循环次数
            for (int binCount = 0; ; ++binCount) {
                    // 将p节点的next节点赋值给e,判断e==null
                    if ((e = p.next) == null) {
                        // 在tab[index]的节点p.next赋值
                        p.next = newNode(hash, key, value, null);
                        //当binCount=7,treeifyBin()
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    //e!=null
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
        }
        //在put第13个不同的key时,进行扩容。12->13
        //大小为16的table表中里存13个Node时,开始扩容resize();
        // Node<K,V>[] resize()->{
        //     //创建新的变量接收老的数组
        //     Node<K,V>[] oldTab = table;
        //     int threshold = newCap = table.length << 1= 16 <<1 =32;
        //     int newThr = oldThr << 1 = 24;
        //     //new 大小为32的Node数组
        //     Node<K,V>[] table = newTab = (Node<K,V>[])new Node[newCap];
        //     if (oldTab != null) {
        //      //循环旧的table ,存了13个值,循环16次
        //      for (int j = 0; j < oldCap; ++j) {
        //        //创建临时变量
        //        Node<K,V> e;
        //        //oldTab[0]不为空,将oldTab数组值赋值给e
        //        if ((e = oldTab[j]) != null) {
        //            //将数组oldTab[0]置为null
        //            oldTab[j] = null;
        //            //判断e节点的next节点
        //            if (e.next == null)
        //                //计算index,将e.hash与新的容量32作&
        //                //并赋值
        //                newTab[e.hash & (newCap - 1)] = e;
        //            //判断该节点为树节点
        //            else if (e instanceof TreeNode)
        //                ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
        //            //e.next !=null
        //            else { // preserve order
        //                //常见多个临时变量
        //                Node<K,V> loHead = null, loTail = null;
        //                Node<K,V> hiHead = null, hiTail = null;
        //                Node<K,V> next;
        //                //循环,将e = e.next
        //                do {
        //                    //next为e.next
        //                    next = e.next;
        //                    //判断e.hash & oldCap==0
        //                    //  则 loHead=loTail=e
        //                    //  否则 hiHead=hiTail=e
        //                    if ((e.hash & oldCap) == 0) {
        //                        if (loTail == null)
        //                            loHead = e;
        //                        else
        //                            //给前一个节点的next赋值e
        //                            loTail.next = e;
        //                        //重置loTail,赋值为当前e
        //                        loTail = e;
        //                    }
        //                    else {
        //                        if (hiTail == null)
        //                            hiHead = e;
        //                        else
        //                            hiTail.next = e;
        //                        hiTail = e;
        //                    }
        //                } while ((e = next) != null);
        //                // 在newTab[j] 上的Node对象循环结束,
        //                // e=null,
        //                // 将loTail.next =null
        //                if (loTail != null) {
        //                    //低链尾部节点的next置为null
        //                    loTail.next = null;
        //                    newTab[j] = loHead;
        //                }
        //                // hiTail
        //                // j+16=hiHead节点
        //                if (hiTail != null) {
        //                    //高链尾部节点的next置为null
        //                    hiTail.next = null;
        //                    newTab[j + oldCap] = hiHead;
        //                }
        //            }
        //        }
        //    }
        //  }
        //  return newTab;
        // }
        if (++size > threshold)
            resize();
    }    
}

//HashMap内部类的Node数据结构
// 该类有key和key对应的hash值,及value,和下一个Node数据。
static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值