JDK8 HashMap源码(一) putMapEntries解析

putMapEntries函数会被HashMap拷贝构造函数public HashMap(Map<? extends K, ? extends V> m)或者LinkedHashMap类的构造函数public LinkedHashMap(Map<? extends K, ? extends V> m)函数调用到

putMapEntries方法


        /**
         * 实现了 Map.putAll 和 Map 的构造
         * 该函数用于将一个map赋值给新的HashMap
         * @param m 传入map的集合
         * @param evict 最初构建此映射时为false,否则为true
         */
        final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
            // 获取传入map集合的大小
            int s = m.size();
            // 如果大小大于0
            if (s > 0) {
                // 判断"表"节点是否有初始化
                if (table == null) { // pre-size
                    // 将map集合大小除以负载因子h后+1,可以得到HashMap所需的最大负载容量,也就是阈值
                    // 因为会计算出小数因此+1.0F向上取整
                    float ft = ((float)s / loadFactor) + 1.0F;
                    // 当不大于最大容器值的时候使用计算出来的ft的长度
                    // 否则如果大于,则使用的是最大容器的值
                    int t = ((ft < (float)MAXIMUM_CAPACITY) ?
                            (int)ft : MAXIMUM_CAPACITY);
                    // threshold 要调整大小的下一个大小值(容量*负载系数)
                    // 如果t大于当前最大负载容量,则进行调整
                    if (t > threshold)
                        // 返回给定目标容量的两个大小的幂
                        threshold = tableSizeFor(t);
                }
                //说明table已经初始化过了.判断传入map的size是否大于当前map的threshold,如果是,必须要resize
                //这种情况属于预先扩大HashMap容量,再put元素
                else if (s > threshold)
                    // 将表格大小初始化或加倍
                    resize();
                // 将map中的元素逐一添加到HashMap中
                for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
                    K key = e.getKey();
                    V value = e.getValue();
                    putVal(hash(key), key, value, false, evict);
                }
            }
        }

  • float ft = ((float)s / loadFactor) + 1.0F这里的加1是因为,size / loadFactor = capacity,但如果算出来的capacity是小数,却又向下取整,会造成容量不够大,所以,如果是小数的capacity,那么必须向上取整
  • 计算出来的容量必须小于最大容量MAXIMUM_CAPACITY,否则直接让capacity等于MAXIMUM_CAPACITY
  • if (t > threshold)这里的threshold成员实际存放的值是capacity的值。因为在table还没有初始化时(table还是null),用户给定的capacity会暂存到threshold成员上去(毕竟HashMap没有一个成员叫做capacity,capacity是作为table数组的大小而隐式存在的)
  • else if (s > threshold)说明传入mapsize都已经大于当前mapthreshold了,即当前map肯定是装不下两个map的并集的,所以这里必须要执行**resize()**操作
  • putval也是使用的默认修饰符,因此只能被本类或者该包下的类访问到,最后循环里的putVal可能也会触发resize操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Naijia_OvO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值