首页 > 其他分享 >关于hashMap的容量为什么是2的幂次方数

关于hashMap的容量为什么是2的幂次方数

时间:2022-11-01 00:12:57浏览次数:45  
标签:0111 CAPACITY hashMap 容量 MAXIMUM initialCapacity 1111 次方

先看hashMap的构造方法

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

可以看见,经过构造方法的相互调用,如果默认无参的话,会得到一个大小为initialCapacity,负载因子为loadFactor的hashMap

其中initialCapacity为16,loadFactor为0.75

static final float DEFAULT_LOAD_FACTOR = 0.75f;
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

注意构造方法的最后一句

this.threshold = tableSizeFor(initialCapacity);

重点:这里就是为什么hashMap的容量为2的幂次方的原因

我们具体走到这个方法里面看看

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;
    }

这里我们举个例子,假如传入的initialCapacity不为2的幂次方时,假如为9

int n = cap - 1;//此时cap为9,这里的n就为8

n |= n >>> 1;//8的二进制为1000,右移一位为0100,然后0100与1000做"|"运算的结果为1100,此时n就被赋值为1100

n |= n >>> 2;//此时n为1100,右移一位为0110,然后0110与1100做"|"运算的结果为1100,此时n就被赋值为1110

n |= n >>> 4;//此时n为1110,右移一位为0111,然后1110与0111做"|"运算的结果为1111,此时n就被赋值为1111

n |= n >>> 8;//此时n为1111,右移一位为0111,然后1111与0111做"|"运算的结果为1111,此时n就被赋值为1111

n |= n >>> 16;//此时n为1111,右移一位为0111,然后0111与1111做"|"运算的结果为1111,此时n就被赋值为1111

return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;//这一步如果n<0就返回1,否则就继续比较,如果n>=MAXIMUM_CAPACITY就返回MAXIMUM_CAPACITY,否则返回n+1

总结:如果initialCapacity是2的幂次方,就返回initialCapacity,否则就返回大于initialCapacity的最近的2的幂次方

为什么initialCapacity一定得是2的幂次方呢?

接下来继续看

int n=tab.length-1
int index = (n - 1) & hash;

这里返回数组下标的时候是用hashcode的值与数组长度取余

因为前面讲过,数组大小一定是2的幂次方,所以这里讲解如果不是2的幂次方会有什么后果

  • 假设数组大小为15,此时n就为14,二进制为0000,1110,假如hashCode的值为0000,0111此时取余为0000,0110
  • 假如hashCode的值为0000,0110此时取余为0000,0110,这里的0000,0110和0000,0111就出现了放入一个数组下标的桶里面,就会浪费一个桶

相反,如果数组大小为2的幂次方的话,(n-1)的值高位全是0,低位全是1,此时hashCode的值就完全决定了放入的桶,且碰撞概率就减小了,也不会出现桶的浪费

这里选择取余操作是因为取余是计算机底层的东西,比取模要快

 

标签:0111,CAPACITY,hashMap,容量,MAXIMUM,initialCapacity,1111,次方
From: https://www.cnblogs.com/happy12123/p/16846381.html

相关文章

  • HashMap详解
    HashMap详解HashMap相关介绍HashMap是Java中的比较常见的集合,主要存放的是键值对,以key-value的形式存储,不是线程安全的。它里面的存储的key和value可以为null值,但是key......
  • Qt下常用的数值计算(绝对值qAbs,最大qMax,最小qMin,开根号Sqrt,N次方是pow,断言宏Q_ASSERT和
    TqAbs(constT&value)Comparesvaluetothe0oftypeTandreturnstheabsolutevalue.ThusifTisdouble,thenvalueiscomparedto(double)0.Example:intabsolu......
  • 浅入浅出 1.7和1.8的 HashMap
    前言HashMap是我们最最最常用的东西了,它就是我们在大学中学习数据结构的时候,学到的哈希表这种数据结构。面试中,HashMap的问题也是常客,现在卷到必须答出来了,是必须会的知......
  • 【精彩内容分享】SoCC 2022 | 大规模云系统自动化容量评估的探索与落地 – DeepScalin
    以下内容来自公众号【蚂蚁技术风险TRaaS】1.前言在线服务提供商比如Google、Facebook、蚂蚁、腾讯等为了保证自身服务的SLO,在进行资源配置时通常会采取“保守”策略:即配置相......
  • go 切片长度与容量的区别
    ###切片的声明切片可以看成是数组的引用(实际上切片的底层数据结构确实是数组)。在Go中,每个数组的大小是固定的,不能随意改变大小,切片可以为数组提供动态增长和缩小的需求,但......
  • 计算机中显示出来的容量往往是硬盘容量的93%左右
    这是由于不同的单位转换关系造成的。在计算机中1GB=1024MB,而硬盘厂家通常是按照1GB=1000MB进行换算的。以120GB的硬盘为例进行举例说明:厂商计算方法:120GB=120000MB=12000000......
  • HashMap
    (1)特点1.HashMap是Map里面的一个实现类;2.没有额外需要学习的特有方法,直接使用Map里面的方法就可以了;3.特点都是由键决定的:无序、不重复、无索引;4.HashMap跟HashSet底层......
  • java-并发集合-并发hash表 ConcurrentHashMap 演示
    java-并发集合-并发hash表 ConcurrentHashMap演示packageme.grass.demo.concurrent;importjava.util.Date;importjava.util.concurrent.Concurr......
  • 时间 存储容量(或带宽)的单位
      时间小写10底数容量大写2底数带宽大写2底数【主存的性能指标计算机系统基础(二)南京大学主讲:袁春风南京大学】https://www.bilibili.com/video/BV1rE41127......
  • 手写 Java HashMap 核心源码
    手写JavaHashMap核心源码手写JavaHashMap核心源码上一章手写LinkedList核心源码,本章我们来手写JavaHashMap的核心源码。我们来先了解一下HashMap的原理。Ha......