TreeSet是基于红黑树的有序集合,按自然顺序或Comparator排序,自动维护有序性,时间复杂度O(log n),不支持重复元素,遍历天然有序,但非线程安全且不可存null(除非自定义Comparator明确允许)。

TreeSet 是 Java 中基于红黑树实现的有序集合,它默认按元素自然顺序排序,也支持通过 Comparator 自定义排序规则。只要元素实现了 Comparable 接口,或者你在创建 TreeSet 时传入 Comparator,就能自动维持插入后的有序状态,无需手动排序。
使用自然排序(元素实现 Comparable)
当存入 TreeSet 的类本身实现了 Comparable 接口,并重写了 compareTo() 方法,TreeSet 就会按该逻辑自动排序。比如 String、Integer 等内置类型已默认实现,可直接用:
-
TreeSet<Integer> set = new TreeSet<>();插入 5, 2, 8 后,遍历结果是 2 → 5 → 8 - 自定义类需实现
Comparable<YourClass>,并在compareTo()中定义比较逻辑(如按 id 升序) - 注意:不能插入
null(除非使用带 Comparator 的构造器且明确允许)
使用自定义排序(传入 Comparator)
若不想修改类源码,或需要多种排序方式,可在构造 TreeSet 时传入 Comparator。支持 Lambda 表达式、方法引用或匿名内部类:
- 按字符串长度升序:
new TreeSet<>((a, b) -> a.length() - b.length()) - 按 Person 的 age 降序:
new TreeSet<>(Comparator.comparingInt(p -> p.age).reversed()) - 多个字段组合排序:先按 name 升序,name 相同时按 age 降序:
Comparator.comparing(Person::getName).thenComparing(Person::getAge, Comparator.reverseOrder())
保持排序状态的关键机制
TreeSet 的“自动排序”不是靠插入后重新排序整个集合,而是利用红黑树结构,在每次 add()、remove() 时动态调整节点位置,保证中序遍历始终有序。因此:
立即学习“Java免费学习笔记(深入)”;
- 插入、删除、查找时间复杂度都是 O(log n),比 ArrayList 排序后查更快
- 不支持重复元素(基于
equals()和compareTo()判断是否重复,二者需保持一致) - 遍历时(如增强 for 循环或迭代器)天然按排序顺序返回,无需额外调用 sort
常见陷阱与注意事项
实际使用中容易忽略几个细节:
-
compareTo()返回 0 表示相等,TreeSet 会认为两个对象相同,后者不会被添加 - 如果自定义 Comparator 与
equals()不一致(例如只比 id,但 equals 比 name+id),可能导致 set 行为异常(如 contains 返回 false) - TreeSet 不是线程安全的,多线程环境下需外部同步,或用
Collections.synchronizedSortedSet() - 不能用
TreeSet(Collection)构造器批量初始化未排序集合——它仍会逐个 add 并重建树,不是简单复制


















