TreeSet默认自然排序,自定义排序需传入Comparator对象;compare(a,b)返回负数、0、正数分别表示a小于、等于、大于b;支持匿名内部类、Lambda(推荐)和独立Comparator类三种方式;注意null处理、一致性要求及对象字段不可变性。

TreeSet 默认按自然顺序排序,若要自定义排序规则,需在构造时传入实现 Comparator 接口的对象。关键在于:Comparator 的 compare(a, b) 方法决定元素大小关系,返回负数、0、正数分别表示 a 小于、等于、大于 b。
使用匿名内部类定义 Comparator
适合简单、一次性的排序逻辑,比如按字符串长度升序:
TreeSet<String> set = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length()); // 升序
}
});
set.add("Java"); // length=4
set.add("Go"); // length=2
set.add("Python"); // length=6
// 结果顺序:Go, Java, Python
使用 Lambda 表达式(推荐,简洁)
JDK 8+ 支持 Lambda,大幅简化写法。同样按长度排序可写为:
TreeSet<String> set = new TreeSet<>((s1, s2) ->
Integer.compare(s1.length(), s2.length())
);
- 若想降序,交换参数位置:
(s1, s2) -> Integer.compare(s2.length(), s1.length()) - 支持链式比较,例如先比长度、再比字典序:
(s1, s2) -> { int lenCmp = Integer.compare(s1.length(), s2.length()); return lenCmp != 0 ? lenCmp : s1.compareTo(s2); }
复用独立的 Comparator 类
当排序逻辑复杂或需多处使用时,建议单独定义类:
立即学习“Java免费学习笔记(深入)”;
public class PersonAgeComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return Integer.compare(p1.getAge(), p2.getAge());
}
}
// 使用
TreeSet<Person> people = new TreeSet<>(new PersonAgeComparator());
- 也可让
Person实现Comparable,但 Comparator 更灵活——不侵入业务类,且支持多种排序策略 - 注意:Comparator 中的比较逻辑必须满足“一致性”——对同一对对象多次调用必须返回相同结果;不能依赖可变字段(如当前时间)
注意事项与常见坑
- TreeSet 不允许插入
null元素(除非 Comparator 显式处理 null,如使用Comparator.nullsFirst()) - 如果 Comparator 判定两个对象相等(
compare(a,b)==0),TreeSet 视为重复元素,后者不会被添加 - 修改已存入 TreeSet 的对象字段(影响比较结果)可能导致集合结构错乱,应避免;如需更新,先
remove再add


















