hashmap根据键获取值的核心是哈希定位加链表或红黑树查找,平均时间复杂度为o(1);先调用key.hashcode()并经扰动函数处理,再通过(n-1)&hash快速定位桶,桶内依次比对equals()或走红黑树查找。

HashMap 根据键获取值的核心是 哈希定位 + 链表/红黑树查找,平均时间复杂度为 O(1),前提是哈希函数分布均匀、负载因子合理。
哈希计算与桶定位
调用 get(key) 时,HashMap 先对键调用 key.hashCode(),再通过扰动函数(高位参与运算)和位运算(& (table.length - 1))快速算出数组下标(即“桶”的位置)。这比取模更高效,但要求容量始终是 2 的幂次。
桶内查找逻辑
定位到桶后,按以下顺序查找:
- 若桶中第一个节点的 key 与传入 key 完全相等(
==或equals()为 true),直接返回其 value - 若该桶是链表结构,遍历链表,逐个比较 key 的
equals() - 若该桶已树化(节点数 ≥ 8 且 table.length ≥ 64),则走红黑树的
getTreeNode()查找,时间复杂度为 O(log n)
保证高效的关键前提
以下几点直接影响 get 性能:
- 键的 hashCode() 必须稳定:对象在作为 key 存入后,若其 hashCode 改变(如修改了影响哈希值的字段),将无法被正确查到
- equals() 和 hashCode() 要保持一致:两个逻辑相等的 key,hashCode 必须相同;否则可能落入不同桶,导致查不到
-
初始容量和负载因子要合理:默认初始容量 16、负载因子 0.75,适合多数场景;若预估数据量大,建议构造时指定足够容量(如
new HashMap(1024)),避免频繁扩容和 rehash - 键类型尽量用不可变类:如 String、Integer、Long 等,天然满足 hashCode/equals 稳定性要求;自定义类作 key 时,必须正确重写这两个方法
一个小提醒
如果 key 为 null,HashMap 特殊处理——它总放在 table[0] 桶中,且只允许一个 null key。查找时直接检查首节点是否为 null key,不参与哈希计算。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











