HashMap每次扩容为什么是2倍

 更新时间:2024年11月24日 11:52:30   作者:zhangjin1120  
当HashMap在初始化没有指定容量的情况下,首次添加元素时,数组的容量为16;当超出阈值,数组容量为扩容为之前的2倍,为什么HashMap每次扩容都是之前的2倍?下面就介绍一下

当HashMap在初始化没有指定容量的情况下,首次添加元素时,数组的容量为16;当超出阈值,数组容量为扩容为之前的2倍。

为什么HashMap每次扩容都是之前的2倍?而不是像ArrayList首次为10,后续为1.5倍呢?2倍不是很浪费空间吗?

HashMap的putVal方法源码,如下图所示:

其中 n 为数组的长度,n - 1 为数组的最大索引值。(n - 1) & hash 的意思是将每个元素的key的hash值,与最大索引值-1进行相与操作,得出该元素在数组中的位置。hash是添加的元素进过哈希函数计算出来的值。

每次扩容后的数组长度如下表:

与运算的规则如下,只要有一个0,结果就是0;两个同时为1,结果才是1。

1 & 0 = 0
0 & 1 = 0
1 & 1 = 1
0 & 0 = 0

假如HashMap的容量不是2的n次幂,设容量为10,二进制为01010,(n-1)的二进制是01001,向里面添加同样的元素9,12,13,15,结果为:

可以看出,9,13,15得出的结果都是9,index相同,hash碰撞严重。

当HashMap的容量是16时,它的二进制是10000,(n-1)是15,二进制表示是01111,和hash值9,12,13,15进行与运算,计算结果如下:

还是9,12,13,15。可以看出,与运算后得出不同的值,使得添加的元素能够均匀分布在集合中不同的位置上,避免hash碰撞。

综上所述,HashMap计算添加元素的位置时,使用的位运算,这是高效的运算;

另外,HashMap的初始容量是2的n次幂,扩容也是2倍的形式进行扩容,是因为容量是2的n次幂,可以使得添加的元素均匀分布在HashMap中的数组上,减少hash碰撞,避免形成链表的结构,使得查询速度降低!

到此这篇关于HashMap扩容为什么是2倍的文章就介绍到这了,更多相关HashMap扩容2倍内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot中自定义首页(默认页)及favicon的方法

    SpringBoot中自定义首页(默认页)及favicon的方法

    这篇文章主要介绍了SpringBoot中如何自定义首页(默认页)及favicon,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • SpringBoot如何集成Token

    SpringBoot如何集成Token

    文章介绍了如何使用jjwt插件实现Token的生成和校验,该插件可以直接与SpringBoot集成,Token由三部分组成,分别是header、payload和signature,通过在请求头中传递Token,后端可以验证其合法性,从而提高安全性
    2025-01-01
  • Java超详细梳理IO流的使用方法上

    Java超详细梳理IO流的使用方法上

    流(Stream)是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道,数据源发送的数据经过这个通道到达目的地,按流向区分为输入流和输出流
    2022-04-04
  • MyBatis-Generator的配置说明和使用

    MyBatis-Generator的配置说明和使用

    本文主要介绍了MyBatis-Generator的配置说明和使用的相关知识。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • Java乐观锁防止数据冲突的详细过程

    Java乐观锁防止数据冲突的详细过程

    乐观锁是一种并发控制机制,用于防止多个事务同时修改同一数据导致的数据不一致问题,它通过在数据记录中添加一个版本号或时间戳字段,来判断数据在两次操作之间是否被其他事务修改本文介绍了乐观锁防止数据冲突的详细过程
    2025-04-04
  • 浅谈java8 stream flatMap流的扁平化操作

    浅谈java8 stream flatMap流的扁平化操作

    这篇文章主要介绍了浅谈java8 stream flatMap流的扁平化操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Druid如何平行替换为Hikari

    Druid如何平行替换为Hikari

    这篇文章主要介绍了Druid如何平行替换为Hikari问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • Java中的CompletableFuture详解

    Java中的CompletableFuture详解

    这篇文章主要介绍了Java中的CompletableFuture详解,Future接口(FutueTask实现类)定义了操作异步任务执行一些方法,如获取异步任务的执行结果、取消任务的执行、判断任务是否被取消、判断任务执行是否完毕等,需要的朋友可以参考下
    2023-09-09
  • Java编程实现遍历两个MAC地址之间所有MAC的方法

    Java编程实现遍历两个MAC地址之间所有MAC的方法

    这篇文章主要介绍了Java编程实现遍历两个MAC地址之间所有MAC的方法,涉及Java针对MAC的遍历获取与字符串转换相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-11-11
  • 详解Java之冒泡排序与选择排序

    详解Java之冒泡排序与选择排序

    这篇文章主要为大家介绍了Java之冒泡排序与选择排序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12

最新评论