Java 概念小课(一):HashMap 底层到底是怎么工作的

举报
yd_236430038 发表于 2026/10/22 21:18:30 2026/10/22
【摘要】 Java 概念小课(一):HashMap 底层到底是怎么工作的HashMap 大概是 Java 里用得最多的容器,但很多人对它的理解停留在「键值对」三个字。这篇用最短的篇幅把它的核心机制讲清楚。 一句话总结HashMap = 数组 + 链表 + 红黑树。数组是主体,冲突的元素挂在链表上,链表太长了就升级成红黑树。 put 的完整流程Map<String, Integer> map = ne...

Java 概念小课(一):HashMap 底层到底是怎么工作的

HashMap 大概是 Java 里用得最多的容器,但很多人对它的理解停留在「键值对」三个字。这篇用最短的篇幅把它的核心机制讲清楚。

一句话总结

HashMap = 数组 + 链表 + 红黑树。数组是主体,冲突的元素挂在链表上,链表太长了就升级成红黑树。

put 的完整流程

Map<String, Integer> map = new HashMap<>();
map.put("ant", 1);

这一步内部发生了什么:

  1. 算哈希:(h = key.hashCode()) ^ (h >>> 16),把高 16 位混进低 16 位,减少冲突;
  2. 定位桶:用哈希值对数组长度取模(实现上是位运算 (n - 1) & hash,因为数组长度永远是 2 的幂);
  3. 桶为空:直接放入,结束;
  4. 桶不空:key 相同(equals 为 true)就覆盖,不同就挂到链表尾部;
  5. 树化:链表长度 ≥ 8 且 数组长度 ≥ 64 时,链表转红黑树,查询从 O(n) 变 O(log n)。

几个高频问题

为什么容量必须是 2 的幂?

为了让 (n - 1) & hash 等价于取模。n 是 2 的幂时,n - 1 的二进制全 1,位运算结果和取模一致,但快得多。

什么时候扩容?

负载因子默认 0.75。元素数超过 容量 × 0.75 时扩容为原来的 2 倍,并把所有元素重新分布(rehash)。扩容后元素要么留在原位置,要么移动到「原位置 + 旧容量」,只需看哈希的新增那一位是 0 还是 1。

为什么树化阈值是 8?

理想哈希分布下链表长度服从泊松分布,长度到 8 的概率约千万分之一。树化是防哈希碰撞攻击的兜底,不是常态。

HashMap 线程安全吗?

不安全。多线程场景用 ConcurrentHashMap(JDK 8 后是「数组 + 链表/红黑树 + CAS + synchronized 锁桶头」,锁粒度很小),而不是早已过时的 Hashtable。

小结

  • 定位靠哈希,冲突靠链表,链表长了变红黑树;
  • 0.75 负载因子触发 2 倍扩容;
  • 多线程请直接用 ConcurrentHashMap。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。