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)

相关推荐
Patrick在香港6 分钟前
Python Docker镜像从1.2GB到89MB:多阶段构建的完整优化实录
java·python·docker·信息可视化·容器·数据分析·ai编程
上海安当技术18 分钟前
敏感数据怎么防拖库?信封加密(DEK+KEK 二层密钥)架构设计与 Java 实战
java·开发语言·python
我是唐青枫27 分钟前
Java JCommander 实战详解:用注解解析命令行参数
java·开发语言
大鹏说大话35 分钟前
C++ 内存布局详解:类、虚函数、虚表底层原理
java·开发语言
键盘会跳舞1 小时前
C++:容器适配器 queue 的源码级拆解
开发语言·c++·queue
还是鼠鼠1 小时前
Spring AI连接DeepSeek与通义千问:application.yaml配置详解
java·通义千问·spring ai·deepseek
计算机小白一个2 小时前
蓝桥杯 Java B 组之哈希表应用(两数之和、重复元素判断)
java·数据结构·算法·蓝桥杯
Loge编程生活2 小时前
打卡信奥刷题(3449)用C++实现信奥题 P10429 [蓝桥杯 2024 省 B] 拔河
开发语言·数据结构·c++·算法·青少年编程
在世修行3 小时前
从零打造 C# 工业视觉检测系统(八):Modbus RTU 协议解析与 PLC 剔除控制实战
开发语言·c#
万物皆智能3 小时前
AI合规面试:AI合规常见面试题与答题思路
人工智能·面试·职场和发展