Stream API处理集合分三步:filter按条件筛选、sorted依自然序或Comparator排序、collect归集为List/Set/Map等;链式调用、不可变、延迟执行,注意Stream不可复用及空值安全。

用Stream API对泛型集合做过滤、排序和归集,核心是三步:先用filter筛出目标元素,再用sorted排好顺序,最后用collect收集成你需要的结构。整个过程链式调用、不修改原集合,也无需手动写循环。
过滤:精准保留符合条件的元素
filter接收一个Predicate,只留下返回true的元素。适用于单条件或组合条件:
- 基础写法:比如从
List<Integer>中取偶数:list.stream().filter(n -> n % 2 == 0) - 对象筛选:如
List<User>中找年龄≥25且姓名以“A”开头的用户:users.stream().filter(u -> u.getAge() >= 25 && u.getName().startsWith("A")) - 多条件复用:可提前定义Predicate并用
and()/or()组合,提升可读性和复用性
排序:支持自然序、自定义序与多级排序
sorted本身可直接用于String、Integer等自然有序类型;处理对象时需配合Comparator:
- 按单字段升序:例如按用户名排序:
.sorted(Comparator.comparing(User::getName)) - 降序排列:在比较器后加
.reversed(),如.sorted(Comparator.comparing(User::getAge).reversed()) - 多级排序:先按年龄升序,年龄相同时按姓名降序:
.sorted(Comparator.comparing(User::getAge).thenComparing(User::getName, Comparator.reverseOrder())) - 空值安全:用
Comparator.nullsFirst()或nullsLast()避免NPE
快速归集:灵活转成List、Set、Map或统计结果
collect是终止操作,必须有,否则前面所有操作不会执行。常用归集方式包括:
- 转回List:
.collect(Collectors.toList())(注意:Java 16+推荐Collectors.toUnmodifiableList()防误改) - 去重转Set:
.collect(Collectors.toSet());若需按对象唯一字段去重,得配合自定义Predicate(如用ConcurrentHashMap.newKeySet()实现) - 转Map:
.collect(Collectors.toMap(User::getId, Function.identity())),注意key重复会抛异常,可用三参数重载指定冲突解决策略 - 聚合统计:如求总数
.count()、最大值.max(Comparator)、平均值.collect(Collectors.averagingDouble(User::getSalary))
注意事项与实用技巧
实际使用中几个关键点容易影响结果或性能:
- Stream不能复用:一旦执行过终止操作(如collect),该Stream就关闭,再次调用会报IllegalStateException
- 延迟执行:filter/map/sorted等中间操作不立刻运行,只有遇到collect/forEach/count等终止操作时才真正触发
- 并行处理:大数据量时可改用
parallelStream(),但要注意线程安全,尤其在自定义Collector或副作用操作(如forEach里修改外部变量)中 - 空值处理:map前建议用Optional包装,或用filter先排除null,避免NullPointerException

















