4.24-HashMap构造方法源码学习

发布时间:2022-06-08 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了4.24-HashMap构造方法源码学习脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

HashMap有4个构造方法,分别是无参的构造方法,1个参数的构造方法,2个参数的构造方法等,分别如下:

无参构造方法,默认capacity(容量为16),loadFactor = 0.75f

4.24-HashMap构造方法源码学习

1个参数的构造方法,默认负载因子是0.75f,其中初始化容量为你传入的初始化容量的2^n,调用2个参数的构造方法:

4.24-HashMap构造方法源码学习

2个参数的构造方法

Constructs an empty HashMap with the specified initial capacity and load factor. Params: initialCapacity – the initial capacity //初始化容量 loadFactor – the load factor //负载因子 Throws: IllegalArgumentException – if the initial capacity is negative or the load factor is nonpositive

 public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)  //说明初始化容量不能小于0
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY) //初始化容量不能大于MAXIMUM_CAPACITY,就是1 << 30, 为啥不是 1<<31呢?因为int的容量为 -2^31-2^31-1
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor)) //说明负载因子必须>0,如果小于0是不行的
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        this.loadFactor = loadFactor; //负载因子
        this.threshold = tableSizeFor(initialCapacity); //临界值,就是传说中的initialCapcity*loadFactor
    }
  • 小伙伴们对构造方法熟悉了吗?其实里面最重要的是tableSizeFor(initalCapcity);这个方法,点击去,我们发下如下:
static final int tableSizeFor(int cap) { //初始化容量,可以为0的
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }
  • 看到这里小伙伴们惊奇了,这到底是个啥?一堆位运算, >>> 是啥? |=是啥?,且容我慢慢道来,欢迎大佬留言指正
  • 首先 |= 是 或等于, 譬如 n |= 1, 就是 n = n | 1的意思,那 n = n| 1 到底是啥呢?没错,就是将最低位 置为1, 只要有1就是1
  • 那么 n >>> 1到底是啥呢?对于正数而言, n >> 1 和 n >>> 1是相等的,就是 右移 1位的意思,不要忘记 cap可以是0啊
  • 那上面一堆操作是啥呢?没错,就是扩容,很巧妙啊, 1+2+4+8+16正好是31,最高位是符号位,若是我是 0x0000ff00的话,结果就是 0x0000ffff了,就是传说中的大于cap的最小的 2^n - 1 啊,还没完呢,记着 这个函数返回值给threshold 了吗?没错,这个可是扩容的临界值啊,为啥和传说中的不一样呢?不应该是初始化容量*负载因子吗?为啥是将最高位(非符号位且位1)后面的位数统统置为1呢?

最后一个构造方法

/*
Implements Map.putAll and Map constructor.
Params:
m – the map //传入的map
evict – false when initially constructing this map, else true (relayed to method afterNodeInsertion).
*/
 public HashMap(Map<? extends K, ? extends V> m) {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        putMapEntries(m, false);
    }


 final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
        int s = m.size();
        if (s > 0) {
            if (table == null) { // pre-size
                float ft = ((float)s / loadFactor) + 1.0F;
                int t = ((ft < (float)MAXIMUM_CAPACITY) ?
                         (int)ft : MAXIMUM_CAPACITY);
                if (t > threshold)
                    threshold = tableSizeFor(t);
            }
            else if (s > threshold)
                resize();
            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); //这一步数组才真正的初始化
            }
        }
    }

本人才疏学浅,写这个主要是为了学习打卡用,可能存在缺陷,欢迎大佬留言指正

脚本宝典总结

以上是脚本宝典为你收集整理的4.24-HashMap构造方法源码学习全部内容,希望文章能够帮你解决4.24-HashMap构造方法源码学习所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: