⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 小哈学Java 「犬小哈」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

面试官到底想考什么?

别天真地以为面试官只想听你背一个数字。这道题是个照妖镜,能暴露你的技术深度:

  1. 你懂不懂 HashMap 的底层? 负载因子、哈希冲突、扩容——这三者是铁三角关系,答不清楚就是没读过源码。
  2. 你有没有 Trade-off 思维? 工程里没有银弹,只有取舍。0.75 不是神谕,是妥协。
  3. 你碰过泊松分布吗? 这个数字背后有数学推导,不是拍脑袋定的。
  4. 你翻过 JDK 源码吗? HashMap.java 的注释里白纸黑字写着为什么是 0.75,看过的人和没看过的人,答案质量差一个档次。
  5. 你能活学活用吗? 知道什么场景该调高、什么场景该调低,才是真本事。

一句话答案

0.75 是时间和空间的最佳平衡点。

再展开一点:这个数字让哈希桶有 75% 的填充率时触发扩容。太高(如 1.0)会导致冲突爆炸、链表变长、查询变慢;太低(如 0.5)会频繁扩容、浪费内存。0.75 刚好踩在性能和内存的甜点上。

深入理解:负载因子的本质

扩容的触发器

负载因子 = 已存元素数 / 桶数组长度

当这个比值超过阈值(默认 0.75),HashMap 就会触发 resize():数组容量翻倍,所有元素重新哈希分配。这是个 O(n) 的重操作,所以你不希望它频繁发生。

两个极端,两种死法

负载因子 空间利用率 冲突概率 结局
1.0(满了才扩) 极高 极高 链表变长,get()/put() 退化成 O(n),慢到怀疑人生
0.5(半满就扩) 极低 极低 频繁扩容,内存翻倍再翻倍,钱包在哭泣
0.75(甜点) 较高 较低 两边都不吃亏,JDK 的选择

0.75 背后的数学:泊松分布

JDK 源码注释里有一段硬核推导,核心结论是这样的:

假设哈希函数足够随机,元素在桶中的分布遵循泊松分布。当负载因子为 0.75 时,某个桶里元素数量超过 8 的概率不到千万分之一。

这意味着:在 0.75 的阈值下,绝大多数桶只有 0~1 个元素,冲突几乎可以忽略,get() 基本能保持 O(1)。这不是拍脑袋的经验值,是数学给出的答案。

实战指南:什么时候该动它?

90% 的场景:别动,用默认值。 JDK 开发者比你更懂这个。

但有三种情况可以考虑:

  1. 已知元素数量:构造时直接指定初始容量,避免反复扩容。公式:(int)(expectedSize / 0.75) + 1。
  2. 内存极度紧张:调高到 0.8~0.9,牺牲一点查询速度换空间。
  3. 查询性能要求极致:调低到 0.5~0.6,用空间换时间——但说实话,这种场景很罕见。

Java 8 的兜底:即使链表真的变长了,当长度超过 8 且桶数超过 64 时,链表会转成红黑树,查询从 O(n) 变 O(log n)。所以 0.75 的容错空间其实比你想的大。

两个坑,别踩

坑一:以为 0.75 是”最优解”。 不是。它是”在大多数场景下表现最好的经验值”。没有银弹。

坑二:初始容量设成元素数量。 比如你要存 100 个元素,设 new HashMap<>(100)?错。100 > 100 * 0.75,第 76 个元素插入时就扩容了。正确写法:new HashMap<>((int)(100 / 0.75) + 1),或者更简单,直接 new HashMap<>(134)。

一句话总结

0.75 不是神谕,是工程师们在”查得快”和”省内存”之间反复试错后找到的平衡点。别轻易动它,除非你比 JDK 开发者更懂你的场景。

文章目录
  1. 1. 面试官到底想考什么?
  2. 2. 一句话答案
  3. 3. 深入理解:负载因子的本质
    1. 3.1. 扩容的触发器
    2. 3.2. 两个极端,两种死法
    3. 3.3. 0.75 背后的数学:泊松分布
    4. 3.4. 实战指南:什么时候该动它?
    5. 3.5. 两个坑,别踩
  4. 4. 一句话总结