HashMap 扩容为啥总是 2 的倍数?一场来自底层的“强迫症”探险

原文来自于:zha-ge.cn/java/55

HashMap 扩容为啥总是 2 的倍数?一场来自底层的"强迫症"探险

你有没有发现,Java 的 HashMap 用起来挺香,但扩容这事儿真的很神秘。不是 10、不是 16,就是 32、64,总之永远是 2 的倍数,感觉像 HashMap 内部养了个强迫症的架构师。前阵子项目有个同事问我"为啥不搞个19试试",我直接笑出声:你咋不上天呢?

------话说回来,这种底层"奇怪坚持",肯定是有故事的嘛,所以忍不住自己扒拉了一番,收获了一箩筐"啊哈"时刻。来吧,让我用程序员唠嗑语气跟你扯扯这个 2 的倍数扩容背后的小九九!


位运算的浪漫

起初我单纯以为:"HashMap 老老实实用 2 的倍数,不就是方便大家算一算容量么。"但后来翻了一圈源码,发现人家玩的可不是加减法,而是位运算

看下面这点彩蛋------(别担心,代码不长)

java 复制代码
int index = (n - 1) & hash;

瞅见没?这玩意就是用来定位元素放哪的。 如果 n 是 16(2 的 4 次方),n - 1 就是 15,二进制全是 1, 和 hash 做与运算,不就是变相 hash % n 嘛?关键是------ 这玩意比真正的 % 运算快很多倍,省事又高效, 不用 hashCode 取余,不用管 n 是不是质数,直接掐指算!


诡异的坑爹时刻

那天刚搞懂为啥用 2 的倍数,忍不住想皮一下------ "要不试试把容量设成 9,看看会咋样?"

然后我就掉坑了。 早期 JDK 版本里,你自作聪明塞个 9、15 进去,不会善罢甘休: 首先,元素分布就会特别丑------好几个 hashCode 虽然不一样, 结果 &(按位与)出来还是同一个桶, 明明人多桶多,却扎堆到一块儿。 极端点,所有元素全挤一个链表里...... WTF,红黑树都救不了你!

再扒拉一遍扩容源码,好家伙,tableSizeFor(capacity) 直接帮你凑最近的 2 的幂。 你想 9?对不起,给你 16。你想 33?那就 64。老板不让穷,也不让抠!


踩坑瞬间

敲重点!真·苦主现场------

  • 指定了一个"看起来挺合理"的初始容量,结果后台日志一看,嘿,为啥变成 16 了?
  • 算 hash 桶的时候,直接 %,性能不如人家 &,慢慢悠悠卡你没商量。
  • 想用特殊大小调优,发现怎么设都不生效,HashMap 自带"自动纠正机制",就是跟你对着干那种......

经验启示

扒拉了这么一遭,得出的教训如下一箩筐:

  • 不要跟源码较劲,HashMap 就爱 2 的幂,任谁来也改不了。
  • 初始化容量随便给,反正 HashMap 会"圆滑"地给你凑个 2 的倍数。
  • 位运算用得妙,比 % 秒杀好几条街:HashMap 的快感,从底层"算桶"开始。
  • 工作里调优容量时,只要量级对了,不用纠结非要贴着需求给数字------源码帮你"切整"。

------写这篇的时候才体会到,所谓"底层优化",有时真就像设计师的强迫症,但细品还真香!


唠叨到这里,是不是解开你心头"2 的倍数强迫症"的谜团了?下次有人再问,你就劝他放下执念、顺应天命。代码世界嘛,有些"规定动作",还是挺有它的艺术的,你说呢?

好了,我要去泡杯咖啡,发会儿呆,下次见记得点我名!

相关推荐
ccccczy_13 小时前
Spring Security 深度解读:JWT 无状态认证与权限控制实现细节
java·spring security·jwt·authentication·authorization·securityfilterchain·onceperrequestfilter
Lin_Aries_042113 小时前
容器化 Tomcat 应用程序
java·linux·运维·docker·容器·tomcat
sheji341613 小时前
【开题答辩全过程】以 springboot高校社团管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
zzywxc78714 小时前
大模型落地实践指南:从技术路径到企业级解决方案
java·人工智能·python·microsoft·golang·prompt
相与还14 小时前
IDEA+SpringBoot实现远程DEBUG到本机
java·spring boot·intellij-idea
小杨勇敢飞14 小时前
IDEA 2024 中创建 Maven 项目的详细步骤
java·ide·intellij-idea
野犬寒鸦14 小时前
从零起步学习Redis || 第四章:Cache Aside Pattern(旁路缓存模式)以及优化策略
java·数据库·redis·后端·spring·缓存
白水先森15 小时前
C语言作用域与数组详解
java·数据结构·算法
草莓熊Lotso16 小时前
从 “Hello AI” 到企业级应用:Spring AI 如何重塑 Java 生态的 AI 开发
java·人工智能·经验分享·后端·spring
doulbQuestion16 小时前
【无标题】
java·spring