Java中Lambda配合Stream实现数据流处理,核心是用filter(Predicate)过滤和collect/reduce等聚合,强调意图清晰、安全高效;filter需前置非空校验,聚合应按场景选合适方法,链式操作须注意顺序以保健壮性。

Java 中 Lambda 表达式配合 Stream API 实现数据流的过滤与聚合,核心是把逻辑写在 filter 和 collect/reduce 等操作里,用简洁、声明式的方式替代传统循环。关键不是“写得短”,而是让每一步意图清晰、安全高效。
过滤:用 filter + Predicate
filter 接收一个 Predicate<T>,也就是返回 boolean 的 Lambda 表达式。它决定哪些元素保留进后续流程。
- 基础写法:
stream().filter(x -> x.getAge() > 18)—— 筛选成年人 - 防空安全:务必前置
filter(Objects::nonNull),避免后续调用空指针 - 多条件组合:可用
&&或||,如filter(u -> u.isActive() && u.getScore() >= 60) - 复用逻辑:可提取为独立 Predicate 变量,提升可读性与复用性
聚合:分场景选对方法
聚合不是只靠 reduce,要按目标选最合适的终端操作:
-
统计数量:直接用
count(),如list.stream().filter(...).count() -
求和/平均/最值:优先走原始类型流,如
mapToInt(User::getSalary).sum(),避免 Integer 装箱开销 -
拼接字符串:用
Collectors.joining(","),支持前缀、分隔符、后缀 -
分组归类:
Collectors.groupingBy(User::getGender),返回 Map<K, List<V>> -
自定义汇总:用
Collectors.collectingAndThen或写自己的 Collector,比如同时统计人数+平均年龄
链式组合:顺序决定结果和健壮性
Stream 操作是惰性的,但执行顺序影响正确性和性能:
立即学习“Java免费学习笔记(深入)”;
-
filter 必须放在 map 前面,尤其当 map 里有方法调用(如
.getName())时,否则 null 会抛异常 - 多个 filter 合并成一个更高效,比如
filter(x -> x.a > 0 && x.b 比两次 filter 少一次遍历 - limit 应在 filter 后使用,如 “取前 5 个有效订单” 是
filter(...).limit(5),不是limit(5).filter(...) - 避免在 map/filter 中做副作用操作(如修改外部变量、发 HTTP 请求),保持 lambda 纯函数特性
实际聚合示例:分组+统计+格式化
比如统计各城市用户数及平均年龄:
Map<String, Double> cityAvgAge = users.stream()
.filter(Objects::nonNull)
.filter(u -> u.getAge() > 0)
.collect(Collectors.groupingBy(
User::getCity,
Collectors.averagingInt(User::getAge)
));
这段代码一次性完成过滤、分组、数值聚合,无需中间集合,也不依赖 for 循环或临时 Map。


















