stream.collect(collectors.tocollection(treeset::new))能自动去重和升序排序,因treeset基于红黑树实现,插入时通过compareto或comparator比较元素,结果为0则拒绝重复,天然保证有序唯一。

用 Stream.collect(Collectors.toCollection(TreeSet::new)) 可以让流在收集过程中自动完成去重和升序排序,核心在于 TreeSet 本身的特性:基于红黑树实现、元素自然排序(或按指定比较器)、不允许重复。
为什么能自动排序与去重
TreeSet 在插入元素时会执行两个关键操作:
- 调用元素的
compareTo()方法(或构造时传入的Comparator)决定插入位置,天然有序 - 如果比较结果为 0,视为重复元素,插入失败,不添加也不报错
因此,只要流中元素类型实现了 Comparable(如 Integer、String、自定义类重写 compareTo),就能直接生效。
基础用法示例
对整数或字符串流直接使用:
List<integer> numbers = Arrays.asList(5, 2, 8, 2, 1, 5);
Set<integer> sortedUnique = numbers.stream()
.collect(Collectors.toCollection(TreeSet::new));
// 结果:[1, 2, 5, 8]</integer></integer>
字符串同理,按字典序排列且去重。
处理自定义对象(需注意可比性)
若元素是自定义类(如 User),必须确保它具备可比性,否则运行时报 ClassCastException:
- 方式一:让类实现
Comparable<user></user>并重写compareTo - 方式二:显式传入
Comparator,更灵活(推荐)
例如按年龄升序:
Set<user> byAge = users.stream()
.collect(Collectors.toCollection(() -> new TreeSet(Comparator.comparing(User::getAge))));
</user>
也可组合多个字段,如先按年龄、再按姓名:
new TreeSet(Comparator.comparing(User::getAge).thenComparing(User::getName))
注意事项与替代建议
注意:TreeSet 不保留插入顺序(本就不需要),且性能略低于 HashSet(O(log n) 插入 vs O(1) 平均);若仅需去重不要求排序,用 Collectors.toSet() 更高效。
如果想先去重再排序(比如用其他集合类型),可分两步:
stream().distinct().sorted().collect(Collectors.toList())- 但这种方式不利用
TreeSet的一次遍历优势,数据量大时不推荐
真正需要“边收边排边去重”时,TreeSet::new 是简洁可靠的选择。











