96SEO 2026-08-15 10:12 0
下面以 JDK 8+ 的 java.util.HashMap 源码实现为主。从底层结构、putget扩容、红黑树化等角度说明 HashMap 的原理,并针对常见的痛点进行主要标注。
JDK 8 之后HashMap 的底层结构是:

数组 + 链表 + 红黑树
主要字段大致如下:
transient Node table;// 哈希桶数组
transient int size;按理说,// 当前键值对数量
int threshold;// 扩容阈值
final float loadFactor;// 负载因子,默认 0.75f
再看其中。
table: 哈希桶数组。Node: 链表节点。size: 已存放的键值对数量。话说回来,threshold: 达到该值后触发扩容。loadFactor: 控制空间与冲突的折中。再看节点结构,
static class Node implements Map.Entry {
final int hash;final K key,V value;Node next;}
每个元素最终都会落到 table 数组的某个位置上。如果多个 key 落到同一个数组下标,就会形成链表;当链表过长时会转换成红黑树,以防止查询退化为 O。
Pain point: 新手经常不清楚 .put 到底走了哪些分支,导致在大量冲突时出现性能瓶颈。不过,
map.put;public V put {
return putVal。key,value,false,true);}
static final int hash {
int h;return,0 : ) ^;}
-,降低冲突概率。- 对于 null key。返回 0,使其统一落在第一个桶。
final V putVal(int hash。K key,V value,boolean onlyIfAbsent,boolean evict) {
Node tab;说起来,Node p;int n,i,if == null || == 0)
n = ).length;i = & hash,if == null)
tab = newNode;else {
Node e;K k,if (p.hash == hash &&
== key || )))
e = p;else if
e = p).putTreeVal;else {
for {
if == null) {
p.next = newNode;if
treeifyBin;break,}
if (e.hash == hash &&
== key || )))
break;p = e,}
}
if { // 覆盖旧值
V oldValue = e.value;if
e.value = value;return oldValue;}
}
++modCount;if
resize,return null;}
table
-
至于计算桶下标,
& hash.
-
If bucket empty → 创建新节点直接放入。老实说,
-
If bucket not empty:
-
If 第一个节点的 equals/hash 相同 → 覆盖 value。
-
If bucket 为红黑树 → 调用树插入逻辑
-
If 为普通链表 → 遍历链表:
-
If 找到相同 key → 覆盖;
-
If 未找到 → 在链表尾部追加新节点。
-
If 链表长度 ≥ TREEIFY_THRESHOLD。且当前数组长度 ≥ MIN_TREEIFY_CAPACITY,则转化为红黑树。
Pain point: 很多人误以为
Pain point: Poor capacity selection leads to frequent rehashing and uneven distribution.
The default initial capacity is **16**,load factor **0.75** ⇒ threshold **12**. When #entries> threshold→resize.
The conversion thresholds are defined as constants:
Why not treeify immediately?
- Small tables cause many collisions simply because空间太小。此时扩容往往比造树更有效。
Result: Only when桶已足够大且冲突严重时才会引入红黑树,从而将最坏情况从 O 降至 O。老实说,
`HashMap` 判断两个键是否相等的代码片段:
`HashMap` 支持唯一一个 `null` 键:
.get
map.get;public V get {
Node
.get 的主要步骤
&hash
. 为什么 HashMap 的容量必须是 2ⁿ 的幂?
&hash ≈ hash % n。but far faster.
. resize 扩容机制
.resize 主要代码摘录
. 链表何时转换为红黑树?说起来,
. 红黑树节点 `TreeNode`
java
static final class TreeNodehash若相同再比较 key;若仍无法区分,则使用 tieBreakOrder 做兜底排序。怎么说呢,
. HashMap 如何处理哈希冲突?
next 串起来。
场景 时间复杂度
理想情况 O
仅链表冲突严重 O
红黑树化后 O
. Key 相等判断逻辑
hashCode 与 equals且满足 “相等对象的 hashCode 必须相等”。否则会出现查不到或重复存储的问题——这是面试常见陷阱之一。
. Null Key 的特殊处理
null 键都落在数组下标 0 中。null 键的根源——只能有一个。
. JDK 7 与 JDK 8+ 的主要区别
. JDK 7
. JDK 8+
Pain point::即使 JDK 8 已经大幅改进,仍然 **不是线程安全**;并发写操作仍然可能导致数据不一致或抛出 ConcurrentModificationException。推荐在多线程场景使用 {@link java.util.concurrent.ConcurrentHashMap}。
* 面试精简答案 *
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback