登录
首页 >  文章 >  java教程

HashMap存储原理深度解析

时间:2026-01-14 15:02:36 401浏览 收藏

欢迎各位小伙伴来到golang学习网,相聚于此都是缘哈哈哈!今天我给大家带来《HashMap数据存储原理详解》,这篇文章主要讲到等等知识,如果你对文章相关的知识非常感兴趣或者正在自学,都可以关注我,我会持续更新相关文章!当然,有什么建议也欢迎在评论留言提出!一起学习!

HashMap底层是Node数组,每个桶存链表头或红黑树根;哈希冲突时链表存储,链表≥8且数组≥64时转红黑树;通过扰动函数和位运算定位桶;扩容时重新散列,新位置为原位置或原位置+旧容量;null键固定存索引0。

在Java里HashMap是如何存储数据的_HashMap结构原理解析

HashMap用数组存桶,每个桶里挂链表或红黑树

HashMap底层本质是一个Node类型的数组(也叫哈希桶数组),默认长度16。数组每个位置(bucket)不直接存键值对,而是存一个链表头节点或红黑树根节点。当多个键的哈希值映射到同一数组索引时,就发生哈希冲突,这些键值对会以链表形式串在同一个桶里。JDK 8起,若链表长度≥8 数组长度≥64,该链表会升级为红黑树,提升查找效率。

键的哈希值决定它落在哪个桶里

每次put时,HashMap先调用key.hashCode(),再执行扰动函数:
h = key.hashCode(); hash = h ^ (h >>> 16)
这个异或右移操作让高位参与运算,减少低位重复导致的聚集。之后用(n - 1) & hash(n是数组长度,必为2的幂)代替取模运算,快速定位下标。这种设计保证了索引计算高效且分布更均匀。

扩容不是简单复制,而是重新散列

当元素个数超过容量 × 负载因子(默认0.75)时触发扩容,新容量=旧容量×2。关键点在于:
- 原数组中每个非空桶里的所有节点,都要重新计算在新数组中的位置
- 因为新数组长度翻倍,(newCap - 1) & hash的结果只可能等于原位置,或原位置+旧容量
- 所以迁移过程只需按位判断,无需再次调用hash(),也不需遍历比较

null键和null值是特例处理

HashMap允许一个null键和任意数量null值。null键不走常规哈希流程——它被固定放在数组索引0的位置(或第一个桶)。get时遇到null键,直接检查table[0]是否为null节点;put时若发现已有null键,则覆盖value。这种特殊路径避免了对null调用hashCode()抛出NullPointerException。

文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《HashMap存储原理深度解析》文章吧,也可关注golang学习网公众号了解相关技术文章。

前往漫画官网入口并下载 ➜
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>