doublesummarystatistics 是专为流式聚合设计的一次性统计容器,适合在单次 collect 中同时获取最大值、最小值、平均值、计数和总和,如分析订单金额或传感器数据。

DoubleSummaryStatistics 是什么,适合在哪儿用
它不是用来替代 Math.max() 或手写循环的,而是专为流式聚合设计的「一次性统计容器」。适合你在一次 stream().collect() 中同时要最大值、最小值、平均值、计数、总和这五个指标的场景——比如分析一批订单金额、响应时间或传感器读数。
常见错误是把它当普通工具类反复调用:先 collect 一次取 max,再 collect 一次取 average……这样会触发多次遍历,性能直接翻倍还丢掉流的简洁性。
怎么正确 collect 到 DoubleSummaryStatistics
必须用 Collectors.summarizingDouble(),不能 new 它、也不能用 Collectors.toCollection() 塞进去。它内部状态不可变,构造后只能通过 collect 累积。
- 正确写法:
list.stream().collect(Collectors.summarizingDouble(d -> d)) - 错误写法:
new DoubleSummaryStatistics()(无参构造私有,无法直接实例化) - 错误写法:
list.stream().mapToDouble(...).summaryStatistics()(这是DoubleStream.summaryStatistics(),返回的是同名但不同的类,且不支持泛型映射)
注意参数:summarizingDouble() 接收的是 DoubleFunction extends Number>,所以传 d -> d.value 或 MyObj::getPrice 都可以,但别传字符串解析逻辑——那会把异常拖进 collect 过程,破坏统计完整性。
立即学习“Java免费学习笔记(深入)”;
拿到结果后怎么安全取值
DoubleSummaryStatistics 的 getMax()、getMin()、getAverage() 在空流时行为不同:max/min 返回 Double.NEGATIVE_INFINITY/Double.POSITIVE_INFINITY,average 返回 Double.NaN。这不是 bug,是设计如此——但生产代码里直接用可能引发后续计算异常。
- 检查是否为空:用
statistics.getCount() == 0,而不是靠Double.isNaN(statistics.getAverage()) - 避免
getAverage()直接参与除法:NaN 传播快,且0.0 / 0.0也是 NaN - 如果业务要求空输入返回 null 或抛异常,得自己包一层,比如:
return stats.getCount() > 0 ? stats.getAverage() : throw new IllegalStateException("empty")
和手动 reduce 或分多次 collect 比,差在哪
单次 collect 走的是并行流友好的累积器(accumulator + combiner),底层用的是原子更新,比你手写 reduce(new DoubleSummaryStatistics(), ...) 更可靠;而分多次 collect 会导致数据源被遍历 N 次——对 Iterator 或 I/O 流来说,第二次 collect 可能拿不到数据了。
性能上,小数据集差异不大;但超过几千元素、尤其配合 parallelStream() 时,单次 summarizingDouble 的吞吐明显更高,且内存更稳——它不会像你用 OptionalDouble 多次 reduce 那样产生一堆临时对象。
容易被忽略的一点:它只接受 double,不接受 int 或 long。传整数会自动装箱成 Double,但如果你原始数据是 int 流,用 IntSummaryStatistics 更省空间、也更精准(避免浮点误差累积)。










