distinct()依据equals/hashcode去重并保持首次出现顺序,sorted()依赖comparable/comparator排序且不可用于无限流;组合时应先distinct再sorted以提升性能。

Java Stream API 中的 distinct() 和 sorted() 是两个高频、基础但极易用错的中间操作。它们职责明确:一个去重,一个排序;但行为逻辑、适用边界和组合方式需要清楚区分,否则可能得到意外结果或性能问题。
distinct 去重:靠 equals + hashCode,顺序不变
distinct() 依据对象的 equals() 判断是否重复,内部用 HashSet 记录已见元素。这意味着:
- 对基本类型(如 Integer、String)直接可用,无需额外处理;
- 对自定义对象(如 Person),必须重写 equals() 和 hashCode(),否则默认按引用比较,所有对象都被视为不同;
- 它保留元素首次出现的顺序,比如 List.of(4, 2, 3, 1, 4) → [4, 2, 3, 1];
- 它是有状态操作,会占用内存,但可作用于无限流(如 Stream.iterate),边遍历边去重;
- 并行流中不保证输出顺序,如需稳定顺序,建议先用 sequential() 或改用其他方案。
sorted 排序:依赖 Comparable 或 Comparator,不可用于无限流
sorted() 要求全部元素参与比较才能确定最终位置,因此:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 自然排序时,元素必须实现 Comparable(如 String、LocalDate、Integer),否则运行时报 ClassCastException;
- 自定义排序用 Comparator,推荐使用
Comparator.comparing(Person::getAge)或Comparator.comparingInt(User::getId),简洁且类型安全; - 支持链式逆序:
.sorted(Comparator.comparing(String::length).reversed()); - 它不改变元素数量,重复项照常保留;
- 不能用于无限流(如 Stream.generate),会一直等待“收尾”,导致程序卡死。
组合使用:先 distinct 再 sorted 更合理
多数业务场景需要“去重后排序”,应严格按 distinct().sorted() 顺序调用:
- 先去重再排序,数据量更小,排序更快;
- 若反过来写
sorted().distinct(),排序阶段已处理全部原始数据(含重复),浪费计算资源; - 对字符串列表去重并按长度升序:
List
result = words.stream()
.distinct()
.sorted(Comparator.comparing(String::length))
.collect(Collectors.toList());
按字段去重的实用替代方案
distinct() 无法直接按某个字段(如 name)去重,这时可选三种可靠方式:
-
map + distinct:仅需该字段值(如取唯一姓名),用
.map(Person::getName).distinct(); -
filter + 自定义 key 判重:封装成复用工具方法,利用 ConcurrentHashMap 的 keySet 去重:
.filter(distinctByKey(Person::getEmail)); -
Collectors.toMap:按字段作 key,保留首个或最新对象,例如:
.collect(Collectors.toMap(Person::getId, p -> p, (a, b) -> a))(保留第一个)。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










