Java 高级开发面试复盘:HashMap 原理、Spring 核心与分布式 ID 实战
在通往 Java 开发工程师岗位的终面环节,企业往往不再满足于'知道是什么',而是深入追问'为什么这样设计?底层机制是什么?边界场景如何处理?'——这正是高级别技术面试的典型风格。
本文完整还原这场高难度终面的核心问题与深度解析,尤其针对面试者反馈'回答不上来'的痛点(如 HashMap 线程不安全的底层原因、JWT 与 Session 区别不清等),提供专业级回答思路 + 原理图解 + 代码示例 + 调试技巧,助你攻克技术深水区。
一、数据结构:从二叉树到红黑树的演进逻辑
面试官提问: 你对数据结构有了解?二叉树、平衡二叉树、红黑树可以给我介绍下吗?
回答思路(分层递进 + 设计动机):
好的,我从使用场景出发来理解它们的演进:
- 普通二叉搜索树(BST):左子树 < 根 < 右子树。但最坏情况退化为链表(如插入有序序列),查找复杂度从 O(log n) 恶化为 O(n)。
- 平衡二叉树(AVL):通过严格平衡(任意节点左右子树高度差 ≤1)保证 O(log n) 性能。但插入/删除需频繁旋转,写操作开销大。
- 红黑树(Red-Black Tree):是近似平衡的 BST,通过以下规则保证最长路径不超过最短路径的 2 倍:
- 节点是红色或黑色;
- 根是黑色;
- 所有叶子(NIL)是黑色;
- 红色节点的子节点必须是黑色(无连续红);
- 从任一节点到其后代叶子的路径包含相同数目的黑节点。
💡 关键对比:AVL 更适合读多写少场景(如数据库索引);红黑树更均衡,读写混合性能更优,因此被用于 Java TreeMap、Linux 进程调度等。
📌 连环追问预判:'为什么 HashMap 1.8 用红黑树而不用 AVL?' 答:因为 HashMap 的树化是兜底策略(链表过长才触发),写入频率不高,但红黑树实现更简单、旋转次数更少,综合成本更低。
二、HashMap 底层原理:数组 + 链表/红黑树
面试官提问: HashMap 的底层原理是什么?
回答(JDK 1.8 视角):
HashMap 底层是'数组 + 链表 + 红黑树'的混合结构:
- 数组(Node<K,V>[] table):主干,通过 (n - 1) & hash 计算索引(n 为 2 的幂,保证均匀分布)。
- 链表:解决哈希冲突,JDK 1.7 是头插法,1.8 改为尾插法(避免死循环)。
- 红黑树:当链表长度 ≥ 8 且数组长度 ≥ 64 时,链表转为红黑树,提升查询性能(O(n) → O(log n))。
// 简化版 putVal 逻辑
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
// 遍历链表或树
if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
break;
(binCount >= TREEIFY_THRESHOLD - )
treeifyBin(tab, hash);
}

