HashMap的最终长度

今天被问到一个有意思的问题,你自己定义的hashmap长度真的有效吗?

要想了解这个问题,我们可以去源码中寻找答案(此博客中使用的是JDK1.8)

public HashMap(int initialCapacity) {
    this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

以上是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);
}

这是之前方法调用的双参构造方法,乍一看下去就真让人头晕目眩,没事,路要一步一步走,我当时第一眼看下去就想直接关掉电脑,我逐行好好分析一下
在这里插入图片描述
第一二行代码都是判断长度是否合法,一个是最小值,一个是最大值,就像是汽水工厂里的质检员一样,你那瓶汽水太多了冒出来了,我就喝几口让他不至于冒出来。我们从第一行可以看出,最小值是0,如果少于0我就觉得你是来捣乱的,不做了,直接抛出异常,至于最大值,这里用MAXIMUM_CAPACITY来表示的,这个值到底是多大呢
在这里插入图片描述
1左移30位,这个具体值是
在这里插入图片描述
这也说明Hashmap最大长度就是这个值了,就算输入一个亿,那也是这个数

在这里插入图片描述
我们接着看代码,第三行是加载因子的判断,我们先引入加载因子的大概定义,是判断HashMap是否要扩容的阈值条件,它也和我们传入的initialCapacity一样,不能<=0,同时还引入了另一个方法,但是我们本次讨论的内容是传入的长度,所以我们暂且将它放在一边,镜头继续拉回到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;
}

这是啥?一眼望去全是右移操作和按位或操作,但是最复杂的操作往往只需要最简单的运算!
按位或,有一则为一,举个例子,C=A|B,在二进制中,C中的1只会比A多或者一样,对于B也一样,说到这,有些同学可能已经领悟到了一点,这个操作就是将一个数转变为2的N次方数-1(二进制低位置全为1),可能很多同学还是对此保持疑惑,就这几步怎么可能,那么我们再来写一个实例129

第一步操作129-1=128
在这里插入图片描述
我们这里举的例子是一个很极端的例子,只有一个1,但是经过三次右移再进行按位或操作后,变成从最高位开始全1的数,这个数是255,再带入最后一步判断,大于0小于最大值,+1后返回,最终返回值是256
现在思考一下256与129和255之间有什么联系,我们再看一下二进制
在这里插入图片描述
这个操作的核心就是将一个数转换成大于最接近他或者等于它的2的n次方数

因此可得,我们传入的参数如果不是2的次方数,那么就会经过这个转换后成一个2的次方数,我们的疑问就可以解决了。

在这里插入图片描述

本人是一名大三学生,在学习之余写下,如果有不对之处欢迎大家指正哦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HashMap的put方法是用来向HashMap中插入键值对的方法。在put方法中,首先会根据键的hash值计算出该键值对在数组中的索引位置。然后,会创建一个新的Node节点来存储该键值对的信息,包括键、值以及其他相关信息。接下来,如果该索引位置已经存在节点,则会执行替换操作;如果该索引位置为空,则直接将新节点插入该位置。在插入节点的过程中,如果链表长度大于等于7并且Node数组长度大于64,则会将该链表转变成红黑树,以提高插入和查找效率。总之,HashMap的put方法是通过计算hash值来确定键值对在数组中的位置,并使用链表或者红黑树来解决hash冲突问题,并最终将键值对插入到相应位置的方法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [HashMap之put方法详解](https://blog.csdn.net/qq_43112598/article/details/106426120)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [HashMap put方法的源码分析](https://download.csdn.net/download/weixin_38729607/13751823)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值