当前位置: 首页 > news >正文

【Java】一篇详解HashMap的扩容机制!!

如果小伙伴对HashMap的扩容机制不了解,那么这篇文章带你吃透扩容机制,如果对你有帮助,希望可以点赞、收藏!!

HashMap的扩容机制是为了应对元素数量增长导致的哈希冲突加剧问题,通过扩大数组容量来分散元素,保证查询效率。
核心逻辑是:当数组数量超过阈值时,将数组容量翻倍,并将旧数组元素迁移到新数组中。

一、扩容核心参数:

3个关键参数:

  • 容量(capacity):哈希表底层数组的长度,默认初始容量为16(必须是2的幂次)。
  • 负载因子(loadFactor):衡量数组填充程度的阈值比例,默认为0.75
  • 阈值(threshold):出发扩容的临界值,计算公式为:threshold=capacity*loadFactor(16*0.75=12)。

二、扩容触发条件:

当HashMap的元素数量size超过阈值时,触发扩容。
即:if(size>threshold) ->执行扩容

三、扩容完整流程(以JDK1.8为例)

JDK1.8中HashMap底层为 数组+链表+红黑树,扩容流程优化后更高效,步骤如下:

1.计算新容量:

新容量=旧容量×2

2.计算新阈值:

新阈值=新容量×负载因子

3.创建新数组:

根据新容量创建一个更大的数组。

4.迁移元素:

将旧元素中的所有元素(链表/红黑树节点)重新计算索引,迁移到新数组中。

四、关键:元素迁移的索引计算:

由于容量一直为2的幂次,JDK1.8中元素迁移时的新索引可以通过高位判断快速计算,无需重新计算哈希值。

  • 旧容量为oldCap(如 16),新容量为newCap = oldCap × 2(如 32)。
  • 元素在旧数组中的索引为oldIndex(通过 hash & (oldCap - 1) 计算)。
  • 新索引只有两种可能:
    若元素哈希值的第n位(n为oldCap的幂次,如 16 是 2⁴,n=4)为0 → 新索引 = oldIndex
    若第n位为1 → 新索引 = oldIndex + oldCap

五、举例:

假设我们有一个初始状态的HashMap:

  • 容量oldCap = 16(数组索引 0~15),阈值threshold = 12,负载因子0.75

步骤 1:触发扩容

当插入第 13 个元素时,size = 13 > threshold = 12,触发扩容:

  • 新容量newCap = 16 × 2 = 32(数组索引 0~31)。
  • 新阈值newThreshold = 32 × 0.75 = 24。

步骤 2:迁移元素(以两个元素为例)

假设旧数组中有两个元素,哈希值(简化后)如下:

  • 元素 A:hash = 0001 0101(二进制,共 8 位示意)
  • 元素 B:hash = 0011 0101

计算旧索引:

旧容量16的二进制是10000oldCap - 1 = 15(二进制01111)。

  • 元素 A 旧索引:hash & 15 = 0001 0101 & 0000 1111 = 0101 → 5。
  • 元素 B 旧索引:hash & 15 = 0011 0101 & 0000 1111 = 0101 → 5(与 A 哈希冲突,在旧数组索引 5 处形成链表)。

计算新索引:

新容量32是100000oldCap = 16的二进制是10000,关键看哈希值的第 4 位(从 0 开始数,对应 16 的幂次位):

  • 元素 A 的 hash 第 4 位:0001 0101 → 第 4 位是0(从右数第 5 位,因 0~3 位是低 4 位) → 新索引 = 旧索引5。
  • 元素 B 的 hash 第 4 位:0011 0101 → 第 4 位是1 → 新索引 = 旧索引5 + 16 = 21。

迁移结果:

  • 元素 A 从旧数组索引 5 迁移到新数组索引 5。
  • 元素 B 从旧数组索引 5 迁移到新数组索引 21。
    两者在新数组中不再冲突链表被 “打散”,查询效率提高。

六、JDK1.7与1.8扩容的核心差异:

请添加图片描述

七、总结:

  • HashMap通过"容量翻倍+元素迁移"实现扩容,核心目的是减少哈希冲突
  • JDK1.8的优化(如高效索引计算、尾插法)让扩容更高效且安全。
  • 实际开发中,若能预估元素数量,建议初始化时指定容量,如:(new HashMap<>(1000)),减少扩容次数以提升性能。
http://www.xdnf.cn/news/1240579.html

相关文章:

  • 2025年8月4日私鱼创作平台v1.0.4公测版更新发布-完成大部分功能包含关注创作者以及发布作品及合集功能优雅草科技
  • 音视频学习笔记
  • 深入解析 Apache Tomcat 配置文件
  • Planner 5D v2.29.0 安卓高级解锁版,手机3D家装,全套家具免费
  • 鸿蒙开发-端云一体化--云数据库
  • [spring-cloud: 负载均衡]-源码分析
  • Nginx服务做负载均衡网关
  • 【项目实践】在系统接入天气api,根据当前天气提醒,做好plan
  • 基于Java的AI工具和框架
  • 【异常案例分析】使用空指针调用函数(非虚函数)时,没有崩溃在函数调用处,而是崩在被调用函数内部
  • Android Telephony 框架与横向支撑层
  • Android JUnit 测试框架详解:从基础到高级实践
  • Flask + HTML 项目开发思路
  • 开源的现代数据探索和可视化平台:Apache Superset 快速指南 Quickstart
  • Android的UI View是如何最终绘制成一帧显示在手机屏幕上?
  • 阿里云-通义灵码:解锁云原生智能开发新能力,让云开发更“灵”~
  • 福彩双色球第2025089期篮球号码分析
  • 理解 JavaScript 中的“ / ”:路径、资源与目录、nginx配置、请求、转义的那些事
  • 超急评估:用提前计算分摊性能成本
  • go学习笔记:panic是什么含义
  • 工作流绑定卡片优化用户体验-练习我要找工作智能体
  • 豆包1.6+PromptPilot实战:构建智能品牌评价情感分类系统的技术探索
  • 基于Spring Cloud Gateway和Resilience4j的微服务容错与流量控制实战经验分享
  • Solidity智能合约开发全攻略
  • 电商系统想撑住大流量?ZKmall开源商城靠微服务 + Spring Boot3 解决单体架构难题
  • 设计模式-创建型-工厂模式
  • 134页PPT华为项目管理之道PPT
  • 期权投资盈利之道书籍推荐
  • Scrapy爬虫集成MongoDB存储
  • 13.Home-面板组件封装