TreeMap 与红黑树
面试官问:"TreeMap 底层是什么数据结构?"
候选人小李答:"红黑树。"
面试官追问:"红黑树有哪些特性?为什么需要这些特性?"
小李说:"...平衡二叉树?"
面试官继续追问:"那 TreeMap 的 floor() 和 ceiling() 方法有什么用?"
小张彻底答不上来了。
【面试官心理】 TreeMap 是 Java 集合框架中比较"冷门"的成员,但它的有序性是 HashMap 无法替代的。能说清楚红黑树特性、TreeMap 导航方法的候选人,说明有一定的算法和数据结构基础。
一、红黑树基础 🔴
1.1 什么是红黑树
红黑树是一种自平衡的二叉搜索树,它通过颜色和旋转操作来保持平衡:
1.2 红黑树的 5 个特性
1.3 为什么需要红黑树
普通二叉搜索树的问题:
红黑树的解决方案:
【直观类比】 红黑树就像一个会自动调整高度的跷跷板:
- 插入数据时,如果某一边太重(不平衡),会自动调整
- 调整后仍然保持平衡,保证左右高度差不大
- 这样无论查找还是插入,都能保证 O(log n) 的性能
二、TreeMap 核心原理 🔴
2.1 TreeMap 的结构
2.2 节点的定义
2.3 put 方法
2.4 ❌ 错误示范
候选人原话:"TreeMap 和 HashMap 一样,都是 Map,实现也差不多。"
问题诊断:
- 完全不理解两者的根本区别
- HashMap 是哈希表,TreeMap 是红黑树
- HashMap 无序,TreeMap 有序
面试官内心 OS:"这个候选人可能只是背过概念,没有真正理解数据结构的差异。"
【面试官心理】 TreeMap 和 HashMap 的核心区别是"有序 vs 无序"。能说清楚这个区别的候选人,说明理解了这两种数据结构的本质差异。
三、自然排序与自定义排序 🟡
3.1 自然排序
3.2 自定义排序
3.3 自定义对象作为 key
四、导航方法 🟡
4.1 导航方法一览
4.2 导航方法图示
4.3 典型使用场景
场景 1:排行榜
场景 2:会议室预订系统
场景 3:缓存过期处理
TreeMap 的导航方法是面试加分项。能说清楚 floor/ceiling/lower/higher 的区别和用法的候选人,说明对 TreeMap 有实战经验。
五、子 Map 视图 🟡
5.1 subMap 方法
5.2 headMap 和 tailMap
5.3 视图与操作
TreeMap 的 subMap/headMap/tailMap 返回的是视图而非副本。对视图的操作会影响原 Map,删除操作是连锁的。
六、性能对比 🟡
6.1 TreeMap vs HashMap
6.2 何时用 TreeMap
6.3 何时用 HashMap
七、线程安全 🟢
7.1 TreeMap 不是线程安全的
7.2 线程安全方案
如果需要有序且线程安全的 Map,用 ConcurrentSkipListMap。它的性能比 Collections.synchronizedSortedMap 好。
八、面试高频追问 🟡
8.1 第一层追问
面试官:"红黑树的特性是什么?"
候选人:...
正确回答:
- 每个节点非红即黑
- 根节点是黑色
- 叶子节点是黑色
- 红节点的子节点必须是黑色(不能有连续红节点)
- 从任一节点到其每个叶子节点的路径上,黑节点数量相同
8.2 第二层追问
面试官:"红黑树的查找、插入、删除时间复杂度是多少?"
候选人:...
正确回答:都是 O(log n)。因为红黑树是自平衡的二叉搜索树。
8.3 第三层追问
面试官:"TreeMap 和 HashMap 的区别是什么?"
候选人:...
正确回答:
- HashMap:哈希表,O(1) 查找,无序
- TreeMap:红黑树,O(log n) 查找,有序,支持导航方法
8.4 第四层追问
面试官:"TreeMap 的 floorKey() 和 lowerKey() 有什么区别?"
候选人:...
正确回答:
lowerKey(k):严格小于 k 的最大 keyfloorKey(k):小于等于 k 的最大 keyhigherKey(k):严格大于 k 的最小 keyceilingKey(k):大于等于 k 的最小 key
九、生产避坑清单 🟡
9.1 ❌ 常见错误
9.2 性能陷阱
【学习小结】 TreeMap 核心要点:
- 底层是红黑树,查找/插入/删除都是 O(log n)
- 按 key 有序排列
- 支持自然排序和自定义排序
- 导航方法:floor/ceiling/lower/higher
- subMap/headMap/tailMap 返回视图
- 线程不安全,需要线程安全时用 ConcurrentSkipListMap