HashMap浅析二:HashMap的容量初始化

HashMap浅析一

回顾下,在上一章中,分析了为什么HashMap的容量是2的指数幂。是为了key的数组寻址时,做取模运算改为位运算提高效率。

这次就来看看HashMap是如何确保容量一定是2的指数幂的。

Map<String, String> normalMap = new HashMap<>();
Map<String, String> initialCapacityMap = new HashMap<>(11);

这是HashMap比较常用的两种初始化方法,第一种是指定默认的无参构造,第二种是指定容量的构造。
看到这里可能会有疑问了,第二种明明是指定了容量11呀,并不是2的指数幂,这是怎么回事呢?接着往下看。
首先看无参的构造方法:

    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }

可以看到非常简单,仅仅是指定了默认的装载因子,这个装载因子和默认容量会在后续学习中继续探讨。接下来看指定容量的构造:

    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }
    
    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;
        this.threshold = tableSizeFor(initialCapacity);
    }

到这里看到,只是对指定容量和装载因子进行一些简单的校验,容量设置调用了方法tableSizeFor,继续往下看:

    static final int tableSizeFor(int cap) {
        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;
    }

这里就是确定HashMap初始容量的核心代码了,可以看到大量的位运算。

首先是通过校验初始容量大于0和无符号的右移位运算,确保最后的结果是正整数。

上面的位运算可能看起来一脸懵逼,其实原来分析起来也不难。下面就来一步步分析上面的位运算是怎么回事,这里用方向推导的方式进行分析。
1、我们都知道,2的指数幂用二进制表示就是0100 0000这样,即v=2^(n-1),当前例子为2的7次方,即64;
2、而64-1即63用二进制表示呢就是0011 1111,可以看到是比64低一位的全1二进制。
所以上述代码的二进制运算就是通过位移和二进制或运算,得出一个2的指数幂减1的数,再加1从而得出这个2的指数幂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值