0

0

如何避免HashMap频繁扩容造成的性能抖动_预估初始容量的方法

P粉602998670

P粉602998670

发布时间:2026-02-24 11:44:02

|

752人浏览过

|

来源于php中文网

原创

预估hashmap初始容量需先按expectedsize/loadfactor向上取整再对齐2的幂,如800个元素配0.75负载因子应设2048;批量构建应预分配容量或用stream.collect;负载因子需据读写比和内存压力调整;必须重写稳定hashcode和equals。

如何避免hashmap频繁扩容造成的性能抖动_预估初始容量的方法

预估初始容量时,别直接传业务数

很多人看到“要预估容量”,就直接写 new HashMap(800)——这看似合理,实则埋了坑。HashMap内部会把传入的值向上取整到最近的 2 的幂(800 → 1024),但这个过程多了一次位运算+判断,且容易让人误以为“给多少就用多少”。更关键的是:**初始容量必须考虑负载因子**。

  • 默认负载因子是 0.75,意味着容量为 1024 时,最多存 768 个元素才不扩容;若你真要塞 800 个,它会在第 769 次 put 时立刻扩容
  • 正确公式是:initialCapacity = (int) Math.ceil(expectedSize / loadFactor)
  • 然后手动对齐到 2 的幂:比如预估 800、负载因子 0.75 → 800 / 0.75 ≈ 1067 → 向上取整到 2048(不是 1024)
  • 更稳妥的做法是直接用 JDK 提供的静态方法:tableSizeFor(1067)(返回 2048),或干脆写死 new HashMap(2048, 0.75f)

批量构建 Map 时,别在循环里 new HashMap()

List<item></item> 转成 Map<string item></string> 是高频场景,但下面这种写法会让扩容次数不可控:

Map<String, Item> map = new HashMap<>(); // 初始容量 16!
for (Item item : list) {
    map.put(item.id(), item); // 第 13 个就触发第一次扩容
}

尤其当 list.size() 是几百上千时,可能触发 3–5 次扩容,每次都要 rehash 全量已存元素。

Hotpot.ai
Hotpot.ai

AI工具箱(图像、游戏和写作系列工具)

下载
  • ✅ 正确做法:先算总数,再预分配 —— Map<string item> map = new HashMap(list.size() + 1);</string>
  • ✅ 更优(Java 10+):Map<string item> map = list.stream().collect(Collectors.toMap(Item::id, Function.identity()));</string>,底层已做容量预估
  • ⚠️ 注意:list.size() 是精确值,但若后续还会 put 额外键,建议加个 buffer,比如 + 16 或乘以 1.1

负载因子不是固定值,得看你的读写比和内存压力

0.75 是平衡点,不是金科玉律。它背后是时间换空间的权衡:负载因子越高,越省内存,但哈希冲突概率上升;越低,桶数组越稀疏,缓存局部性变差,反而拖慢 get

  • 读多写少、内存宽裕?可设为 0.85f0.9f,比如缓存配置项、枚举映射表
  • 写入极不均匀(比如 key 都是 "user_1", "user_2" 这种递增字符串),或对 GC 敏感?可降到 0.6f,减少冲突链长度
  • 极端情况:短生命周期 Map(如单次请求内构建后即丢弃),甚至可用 new HashMap(16, 1.2f),允许存 19 个再扩容,省一次 resize
  • ⚠️ 别设 > 1.0 还想长期持有——虽然合法,但一旦元素数超阈值又没及时扩容,后续 put 可能退化成链表遍历

hashCode 不稳,再大的初始容量也白搭

扩容本身无法避免,但糟糕的 hashCode() 会让扩容前就卡在长链表上,扩容后还聚集,红黑树都救不了。比如自定义 key 只用一个字段算 hash,或者用 ArrayList 当 key 却没重写 hashCode()

  • ✅ 必须重写 hashCode()equals(),且保持一致
  • ✅ 优先用 Objects.hash(f1, f2, f3),它自动处理 null、混合字段、扰动低位
  • ❌ 避免用可变对象(如未封装的 byte[]ArrayList)作 key —— put 后改内容,get 就找不到
  • ⚠️ 字符串 key 看似安全,但如果大量是 "order_12345", "order_12346" 这种,低位相似,小容量时易碰撞;此时初始容量设大点 + 负载因子略降,比调优 hash 更实际
预估容量这事,表面是数学计算,实际是跟业务节奏、数据分布、GC 压力打配合。最容易被忽略的,不是算错那个 2 的幂,而是忘了 key 的 hash 是否真的散得开——扩容能推迟,但散列质量不行,性能抖动只会换个形式出现。
数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

850

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

246

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

866

2024.03.01

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

638

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

217

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1558

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

642

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1027

2024.03.22

中国研究生招生信息网官方网站入口 研招网网页版在线入口
中国研究生招生信息网官方网站入口 研招网网页版在线入口

中国研究生招生信息网入口(https://yz.chsi.com.cn) 此网站是研究生报名入口的唯一官方网站

34

2026.02.24

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号