TreeMap
想了解的 TreeMap 应该是编程领域(尤其是 Java)中的
简单来说,你可以把它理解成一个 “有序的字典”—— 普通的
TreeMap 集合类,本文从核心概念、特性、使用方法到底层原理,做一个通俗易懂的详细介绍,彻底理解它的用法和适用场景。
一、TreeMap 核心定义
TreeMap 是 Java 集合框架中 Map 接口的一个实现类,属于 java.util 包,它的核心特点是:基于红黑树(一种自平衡的二叉查找树)实现,能够对键(Key)进行自动排序。简单来说,你可以把它理解成一个 “有序的字典”—— 普通的
HashMap 是无序的,而 TreeMap 会按照键的规则自动把键值对排好序,不用你手动处理排序逻辑。二、TreeMap 核心特性
- 有序性
- 默认按键的自然顺序排序(比如 Integer 按数字大小、String 按字典序);
- 也可以通过构造方法传入
Comparator自定义排序规则(比如按字符串长度、按数字倒序)。
- 底层结构
- 基于红黑树实现,红黑树是一种平衡二叉查找树,保证了增删改查的时间复杂度都是
O(log n)(比 HashMap 的O(1)慢,但胜在有序)。
- 基于红黑树实现,红黑树是一种平衡二叉查找树,保证了增删改查的时间复杂度都是
- 不允许键为 null
- 因为排序需要比较键的大小,null 无法参与比较,所以键为 null 会抛出
NullPointerException;值可以为 null。
- 因为排序需要比较键的大小,null 无法参与比较,所以键为 null 会抛出
- 非线程安全
- 多线程环境下使用需要手动同步(比如用
Collections.synchronizedSortedMap()包装),或使用ConcurrentSkipListMap(并发版的有序 Map)。
- 多线程环境下使用需要手动同步(比如用
- 元素唯一性
- 键的唯一性由
equals()和compareTo()/Comparator共同保证(红黑树通过比较判断键是否重复)。
- 键的唯一性由
三、TreeMap 常用方法与示例
下面通过完整代码示例,展示 TreeMap 的核心用法:
1. 基础使用(自然排序)
java
import java.util.TreeMap;
public class TreeMapBasic {
public static void main(String[] args) {
// 1. 创建 TreeMap,默认按键的自然顺序排序(Integer 升序)
TreeMap<Integer, String> treeMap = new TreeMap<>();
// 2. 添加键值对
treeMap.put(3, "张三");
treeMap.put(1, "李四");
treeMap.put(2, "王五");
treeMap.put(4, "赵六");
// 3. 遍历(输出会按键升序排列:1->2->3->4)
System.out.println("默认自然排序结果:");
for (Integer key : treeMap.keySet()) {
System.out.println(key + " : " + treeMap.get(key));
}
// 4. 常用方法
System.out.println("\n键的最小值:" + treeMap.firstKey()); // 输出 1
System.out.println("键的最大值:" + treeMap.lastKey()); // 输出 4
System.out.println("小于等于 3 的最大键:" + treeMap.floorKey(3)); // 输出 3
System.out.println("大于 2 的最小键:" + treeMap.ceilingKey(2)); // 输出 2
System.out.println("移除并返回最小键的键值对:" + treeMap.pollFirstEntry()); // 输出 1=李四
}
}
输出结果:
plaintext
默认自然排序结果:
1 : 李四
2 : 王五
3 : 张三
4 : 赵六
键的最小值:1
键的最大值:4
小于等于 3 的最大键:3
大于 2 的最小键:2
移除并返回最小键的键值对:1=李四
2. 自定义排序(Comparator)
如果想按键的倒序排列,或按自定义规则排序,可传入
Comparator:java
import java.util.Comparator;
import java.util.TreeMap;
public class TreeMapCustomSort {
public static void main(String[] args) {
// 1. 传入 Comparator,按 Integer 键倒序排序
TreeMap<Integer, String> treeMap = new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// 倒序:o2 - o1(升序是 o1 - o2)
return o2 - o1;
}
});
treeMap.put(3, "张三");
treeMap.put(1, "李四");
treeMap.put(2, "王五");
// 遍历(输出按键倒序:3->2->1)
System.out.println("自定义倒序排序结果:");
treeMap.forEach((key, value) -> System.out.println(key + " : " + value));
}
}
输出结果:
plaintext
自定义倒序排序结果:
3 : 张三
2 : 王五
1 : 李四
3. 自定义对象作为键(需实现 Comparable)
如果用自定义对象(比如 User)作为键,必须让对象实现
Comparable 接口(或传入 Comparator),否则会抛出 ClassCastException:java
import java.util.TreeMap;
// 自定义 User 类,实现 Comparable 接口(按 age 升序)
class User implements Comparable<User> {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
// 实现 compareTo 方法,定义排序规则
@Override
public int compareTo(User o) {
// 按年龄升序,若年龄相同按姓名字典序
if (this.age != o.age) {
return this.age - o.age;
}
return this.name.compareTo(o.name);
}
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
public class TreeMapCustomKey {
public static void main(String[] args) {
TreeMap<User, String> treeMap = new TreeMap<>();
treeMap.put(new User("张三", 25), "北京");
treeMap.put(new User("李四", 22), "上海");
treeMap.put(new User("王五", 25), "广州");
// 遍历(按 age 升序,age 相同按 name 排序)
System.out.println("自定义对象键的排序结果:");
treeMap.forEach((key, value) -> System.out.println(key + " : " + value));
}
}
输出结果:
plaintext
自定义对象键的排序结果:
User{name='李四', age=22} : 上海
User{name='张三', age=25} : 北京
User{name='王五', age=25} : 广州
四、TreeMap 适用场景
- 需要有序遍历键值对的场景(比如按时间、数字、字母顺序展示数据);
- 需要快速查找 “最大 / 最小键”“小于 / 大于某个键的最近值” 的场景(比如排行榜、区间查询);
- 不要求极致的增删改查性能,但要求有序的场景(如果追求高性能且无需有序,优先用 HashMap)。
五、TreeMap vs HashMap 核心对比
| 特性 | TreeMap | HashMap |
|---|---|---|
| 底层结构 | 红黑树 | 数组 + 链表 / 红黑树 |
| 有序性 | 按键有序(自然 / 自定义) | 无序(JDK8 后按插入顺序) |
| 时间复杂度 | 增删改查 O (log n) | 增删改查 O (1)(平均) |
| 键是否可为 null | 不可 | 可以(仅一个) |
| 排序支持 | 天然支持 | 需手动排序(如 Collections.sort) |
总结
- 核心定位:TreeMap 是有序的 Map 实现,基于红黑树,能自动对键排序,适用于需要有序遍历或区间查询的场景;
- 关键规则:键必须可比较(实现 Comparable 或传入 Comparator),不允许 null 键,非线程安全;
- 选型建议:无需有序选 HashMap(性能更高),需要有序选 TreeMap,并发场景选 ConcurrentSkipListMap。
*
备注:公众号清汤袭人能找到我,那是随笔的地方
备注:公众号清汤袭人能找到我,那是随笔的地方

浙公网安备 33010602011771号