美文网首页
HashMap的最大容量为什么是2的30次方

HashMap的最大容量为什么是2的30次方

作者: 山东大葱哥 | 来源:发表于2020-01-22 12:04 被阅读0次

    HashMap默认容量

    看过HashMap源代码的同学都知道,HashMap有默认的最小容量和最大容量,最小容量是16,最大容量是2的30次方。

        /**
         * 默认的初始化容量-必须是2的幂
         */
        static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
    
        /**
         * 最大容量,如果任意带参构造函数传入的值大于该数 ,那么替换成该数。
         * 必须是2的幂,小于等于2~30
         */
        static final int MAXIMUM_CAPACITY = 1 << 30;
    

    为什么不是2的31次方?

    由于int类型限制了该变量的长度为4个字节共32个二进制位,按理说可以向左移动31位即2的31次幂,这里为什么不是2的31次方,而是2的30次方呢?
    事实上由于二进制数字中最高的一位也就是最左边的一位是符号位,用来表示正负之分(0为正,1为负),所以只能向左移动30位,而不能移动到处在最高位的符号位,所以最大容量只能是2的30次方。

        public static void main(String[] args) {
            System.out.println(1<<30);
            System.out.println(1<<31);
            System.out.println(1<<32);
            System.out.println(1<<33);
            System.out.println(1<<34);
    
        }
    

    输出结果:

    1073741824
    -2147483648
    1
    2
    4
    

    为什么要满足2的n次方

    至于为什么是2的30次方,不是别的数字或者最大整数,这主要是从性能和分布均匀两方面来考虑的:

    • 加快hash计算速度;
    • 均匀分布,减少hash冲突;

    2的n次方,可以通过位移操作来实现,可以加快hash计算速度,结合按位与计算加快数组下标的计算。例如在HashMap做扩容时,满足2的幂就是相当于每次扩容都是翻倍(就是<<1右移一位),这样扩容时在重新计算下标位置时,只有两种情况,一种是下标不变,另一种是下标变为:原下标位置+扩容前容量,这样扩容后节点移动相对较少,也可以提高性能。。

    可以改善数据的均匀分布,减少hash冲突,毕竟hash冲突越大,代表数组中一个链的长度越大,这样的话会降低hashmap的性能。
    其中关键代码为HashMap中的数组下标计算:i = (n - 1) & hash,该计算方法可以实现一个均匀分布。

    相关文章

      网友评论

          本文标题:HashMap的最大容量为什么是2的30次方

          本文链接:https://www.haomeiwen.com/subject/bzbuzctx.html