Collectors.summarizingLong() 返回 LongSummaryStatistics 实例,封装count、sum、min、max、average五个统计量;不支持null,需预过滤;不接受LongStream,须用Stream配合lambda映射;空流时getAverage()返回NaN,getMin()/getMax()则抛异常。

Collectors.summarizingLong() 返回什么类型
它返回的是 LongSummaryStatistics 实例,不是原始值或 Map。这个对象封装了 count、sum、min、max、average 五个统计量,所有方法都可链式调用,比如 stats.getSum()、stats.getAverage()。
常见错误是试图直接强转成 long 或 Map,结果抛出 ClassCastException;也有人误以为它支持 null 安全——其实只要流中含 null,就会在收集阶段触发 NullPointerException。
必须传入 Function 类型的映射函数
该收集器不接受原始 long 值流(如 LongStream),只适用于引用类型的流(如 Stream<user></user>),且必须通过 lambda 明确指定如何提取 long 字段。
- 正确写法:
users.stream().collect(Collectors.summarizingLong(u -> u.getId())) - 错误写法:
longs.stream().collect(Collectors.summarizingLong(x -> x))(longs是LongStream,得先转成Stream<long></long>) - 若字段可能为 null,务必提前过滤:
stream.filter(Objects::nonNull).mapToLong(...),否则空指针发生在summarizingLong内部,堆栈不易定位
和 mapToLong + summaryStatistics() 的性能差异
两者语义接近,但底层行为不同:Collectors.summarizingLong() 是终端操作,走 collect 路径;而 mapToLong(...).summaryStatistics() 构建的是 LongStream,走专门的数值流优化路径。
立即学习“Java免费学习笔记(深入)”;
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
实测在大数据量(百万级)下,后者通常快 10%–15%,因为绕过了装箱/拆箱和 LongSummaryStatistics 的对象创建开销。不过如果已经处在 Stream<t></t> 流程中,强行切到 LongStream 反而增加转换成本,此时用 summarizingLong 更自然。
注意:summaryStatistics() 返回的也是 LongSummaryStatistics,类型一致,可互换使用其 getter 方法。
average() 返回 double,且可能为 NaN
当输入流为空时,getAverage() 不抛异常,而是返回 Double.NaN。这和 getMin()/getMax() 抛 NoSuchElementException 的行为不一致,容易被忽略。
- 检查空流:先用
stats.getCount() == 0判断,再决定是否调用getAverage() - 避免
NaN传播:不要直接参与后续算术运算,例如stats.getAverage() + 1会得到NaN - 格式化输出时,
String.format("%.2f", stats.getAverage())在 NaN 下输出 "NaN",需前置处理
min/max 在空流下会抛异常,这点和 average 的静默失败形成反差,是实际调试中最常踩的坑。

















