美文网首页开发经验随笔程序员码农的世界
HashMap的最大容量为什么是2的30次方

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

作者: 山东大葱哥 | 来源:发表于2019-06-29 09:17 被阅读10次

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/qjrqcctx.html