TreeMap 核心知识点与面试题解析

TreeMap 核心知识点与面试题解析

一、TreeMap 基础概念

TreeMap 是 Java 集合框架中基于 红黑树(Red-Black Tree) 实现的 Map,具有以下特点:

  • 有序性 :默认按 key 的自然顺序Comparable)或自定义顺序Comparator)排序。

  • 时间复杂度

    • 插入、删除、查找:O(log n)

    • 遍历(如 entrySet()):O(n)(中序遍历)

  • 线程不安全 :需用 Collections.synchronizedMap()ConcurrentSkipListMap 替代。


二、TreeMap 核心实现

1. 底层数据结构:红黑树

  • 红黑树特性

    • 每个节点是红色或黑色。

    • 根节点和叶子节点(NIL)是黑色。

    • 红色节点的子节点必须是黑色(不能连续红节点)。

    • 从任意节点到其叶子节点的路径上,黑色节点数相同(黑高平衡)。

  • 自平衡机制 :通过旋转(左旋/右旋)变色保持平衡。

2. 排序方式

  • 自然排序Comparable):

    java

    java 复制代码
    TreeMap<String, Integer> map = new TreeMap<>(); // 默认按 String 字典序

    自定义排序Comparator):

  • java

java 复制代码
TreeMap<Integer, String> map = new TreeMap<>((a, b) -> b - a); // 降序

三、高频面试题

1. TreeMap 和 HashMap 的区别?

对比项 TreeMap HashMap
底层结构 红黑树 数组 + 链表/红黑树
是否有序 是(按 key 排序) 否(无序)
时间复杂度 O(log n) O(1)(平均)
线程安全
允许 null key 取决于 Comparator 允许(但只能有一个)

2. TreeMap 如何保证有序?

  • 红黑树的中序遍历(左-根-右)会按 key 的顺序输出。

  • 依赖 ComparableComparator 定义排序规则。

3. TreeMap 的 put() 方法流程?

  1. 如果红黑树为空,直接插入为根节点(黑色)。

  2. 按 Comparator 或 Comparable 查找插入位置。

  3. 插入新节点(默认为红色)。

  4. 平衡调整(可能涉及变色和旋转):

    • 如果父节点是红色:

      • 检查叔叔节点:

        • 叔叔是红色 → 变色(父、叔变黑,祖父变红)。

        • 叔叔是黑色 → 旋转 + 变色(左旋/右旋)。

4. 如何实现自定义排序?

java

java 复制代码
// 按 value 排序(需转为 List 再排序)
List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());
list.sort((a, b) -> a.getValue() - b.getValue());

// 或者使用 Comparator
TreeMap<String, Integer> customMap = new TreeMap<>((a, b) -> b.compareTo(a)); // 降序

5. TreeMap 的 ceilingKey() 和 floorKey() 方法作用?

  • ceilingKey(K key):返回 ≥ key 的最小 key(如没有,返回 null)。

  • floorKey(K key):返回 ≤ key 的最大 key(如没有,返回 null)。

java

java 复制代码
TreeMap<Integer, String> map = new TreeMap<>();
map.put(1, "A");
map.put(3, "B");
map.put(5, "C");

map.ceilingKey(2); // 3
map.floorKey(4);   // 3

6. TreeMap 为什么用红黑树而不用 AVL 树?

对比项 红黑树 AVL 树
平衡标准 黑高平衡(宽松) 严格高度平衡(左右子树高度差 ≤1)
插入/删除 最多 3 次旋转(O(1)) 可能需 O(log n) 次旋转
查询效率 O(log n),但常数项较大 更快(严格平衡)
适用场景 适合频繁修改(如 Java 集合) 适合高频查询(如数据库索引)

四、代码实战

1. 按 key 降序排列

java

java 复制代码
TreeMap<Integer, String> map = new TreeMap<>((a, b) -> b - a);
map.put(3, "C");
map.put(1, "A");
map.put(2, "B");

System.out.println(map); // {3=C, 2=B, 1=A}

2. 获取子映射(subMap)

java

java 复制代码
TreeMap<Integer, String> map = new TreeMap<>();
map.put(1, "A");
map.put(2, "B");
map.put(3, "C");
map.put(4, "D");

// 获取 [2, 4) 的子映射
SortedMap<Integer, String> subMap = map.subMap(2, 4);
System.out.println(subMap); // {2=B, 3=C}

五、总结

  • TreeMap 适用于需要有序 key 的场景(如范围查询、排序)。

  • 底层是红黑树,保证 O(log n) 的操作效率。

  • 面试重点

    • 红黑树原理

    • 与 HashMap 的区别

    • 排序方式(Comparable/Comparator)

    • 常用方法(ceilingKey, floorKey, subMap)

相关推荐
编啊编程啊程6 分钟前
gRPC从0到1系列【20】
java·rpc·kafka·dubbo·nio
listhi5207 分钟前
基于MATLAB的高斯混合模型(GMM)实现
开发语言·matlab
兰亭妙微7 分钟前
兰亭妙微QT软件开发经验:跨平台桌面端界面设计的三大要点
开发语言·qt
Mingze031419 分钟前
考研408之栈与队列学习
开发语言·c++·学习·考研·算法
序属秋秋秋39 分钟前
《C++进阶之C++11》【智能指针】(上)
c++·笔记·学习·面试·c++11·智能指针·新特性
循环渐进Forward1 小时前
Go语言:给AI开发装上高性能引擎
开发语言·人工智能·golang
数据知道1 小时前
Go基础:用Go语言操作MySQL详解
开发语言·数据库·后端·mysql·golang·go语言
励志不掉头发的内向程序员1 小时前
【Linux系列】并发世界的基石:透彻理解 Linux 进程 — 进程状态
linux·运维·服务器·开发语言·学习
掘根1 小时前
【Qt】事件
开发语言·qt
毕设源码-赖学姐1 小时前
【开题答辩全过程】以 Python在浙江省人口流动数据分析与城市规划建议的应用为例,包含答辩的问题和答案
开发语言·python·数据分析