summarizingLong 一行代码获取 count、sum、min、max 和 average,返回封装统计信息的不可变 LongSummaryStatistics 对象,支持空值防护与溢出处理,一次性遍历 O(n) 时间复杂度,需配合 mapToLong 使用并注意 null 处理。

用 summarizingLong 可以一行代码同时拿到 count、sum、min、max 和 average,比手动遍历或多次调用 mapToLong + xxx() 更高效也更安全。
summarizingLong 返回的是 LongSummaryStatistics 对象
它不是简单返回几个数字,而是一个封装了全部统计信息的不可变对象,内部已做空值防护和溢出处理(比如 sum 使用 long 类型累加,不会因超限抛异常,但要注意业务上是否接受截断)。
- 调用
.getSum()拿总和 - 用
.getMin()和.getMax()获取极值(空流时 min 返回Long.MAX_VALUE,max 返回Long.MIN_VALUE,需判空) -
.getAverage()返回 double,空流时为 0.0 -
.getCount()是 long 类型元素个数
典型用法:配合 mapToLong 提取数值字段
多数场景要先从对象中提取 long 值,比如统计订单金额、用户 ID 或时间戳:
List<Order> orders = ...;
LongSummaryStatistics stats = orders.stream()
.mapToLong(Order::getAmount) // 注意是 mapToLong,不是 map
.summaryStatistics(); // 即 summarizingLong 的等价写法(summarizingLong 是 collector 版本)
如果坚持用 collector 形式(比如在 reduce 或 groupingBy 中复用),写法是:
立即学习“Java免费学习笔记(深入)”;
OpenJDK 24 Windows x64 官方参考实现(24+36),适合 Windows 环境进行 Java 开发、编译、运行和版本兼容性验证。
LongSummaryStatistics stats = orders.stream()
.collect(Collectors.summarizingLong(Order::getAmount));
大数据量下性能与注意事项
Stream 的 summarizingLong 是一次性遍历完成所有统计,时间复杂度 O(n),比分别调用 sum()、max() 等至少三次遍历更优。
- 并行流下也能正确工作,内部使用
LongSummaryStatistics::combine合并分段结果 - 避免在 lambda 中做复杂计算,否则影响吞吐;提取字段尽量用方法引用
- 如果数据源本身是原始 long 数组,直接用
Arrays.stream(longArr).summaryStatistics(),跳过装箱开销
空集合或 null 元素怎么处理
summarizingLong 本身不处理 null 元素——如果 mapper 返回 null(如 obj -> obj == null ? null : obj.getValue()),会触发 NullPointerException。稳妥做法是提前过滤:
.filter(Objects::nonNull) .mapToLong(obj -> obj.getValue()) // 此时 getValue() 不应返回 null
或者用 Optional 包装再 flatMap,但会增加开销。对关键业务,建议在 mapper 中明确防御性判断,比如:
.mapToLong(o -> o != null ? o.getAmount() : 0L)
这样空对象按 0 计入统计,逻辑更可控。

















