Collectors.summarizingDouble() 适用于需同时获取计数、总和、平均值、最小值、最大值等多统计量且输入为double型数据的场景,底层单次遍历,返回DoubleSummaryStatistics对象,空流时getCount()为0、getAverage()为0.0、getMin()/getMax()分别为POSITIVE_INFINITY/NEGATIVE_INFINITY。

Collectors.summarizingDouble() 能一次性拿到计数、总和、平均值、最小值、最大值,比分别调用 counting()、summingDouble() 等更高效,也避免多次遍历流。
什么时候该用 summarizingDouble() 而不是手动计算
当你需要多个基础统计量(尤其含 min/max),且输入是 double 或可转为 double 的数值型数据时,它比组合多个收集器快——底层只遍历一次流,内部用 DoubleSummaryStatistics 累积状态。
- 适合场景:报表汇总、监控指标聚合、批量数据质量检查
- 不适合场景:只要单一指标(如只求和)、数据含
NaN或Infinity且需特殊处理(它会照常计入) - 注意:若源流为空,返回的
DoubleSummaryStatistics中getCount()为 0,getAverage()返回0.0(不是NaN),getMin()/getMax()返回Double.POSITIVE_INFINITY/Double.NEGATIVE_INFINITY
summarizingDouble() 的参数必须是 ToDoubleFunction
它不接受原始 double 值,而是要一个函数,从每个元素中提取 double。常见写法:
list.stream()
.collect(Collectors.summarizingDouble(item -> item.getPrice())); // item.getPrice() 返回 double 或 Double
- 如果字段是
Double包装类,item.getPrice()为null会触发NullPointerException;务必提前过滤或用Objects.requireNonNullElse(item.getPrice(), 0.0) - 不能直接传
Double::doubleValue除非流元素本身就是Double;若元素是Integer,得写Integer::doubleValue或i -> i.doubleValue() - lambda 里别做重操作(如远程调用、IO),否则拖慢整个收集过程
拿到 DoubleSummaryStatistics 后怎么取值
它不是 Map 或 JSON,而是一个带 getter 的普通对象,取值直接调方法:
立即学习“Java免费学习笔记(深入)”;
DoubleSummaryStatistics stats = list.stream()
.collect(Collectors.summarizingDouble(Item::getPrice));
long count = stats.getCount(); // 注意是 long,不是 int
double sum = stats.getSum();
double avg = stats.getAverage(); // 空流时返回 0.0
double min = stats.getMin(); // 空流时返回 POSITIVE_INFINITY
double max = stats.getMax(); // 空流时返回 NEGATIVE_INFINITY
-
getAverage()返回double,但空流时不抛异常也不返回NaN,这点容易误判为“有数据” - 没有
getVariance()或getStdDev(),如需标准差得自己基于sum、sumOfSquares计算(DoubleSummaryStatistics不提供平方和) - 如果后续还要分组统计,别用这个;改用
groupingBy(key, summarizingDouble(...))
最易被忽略的是空流时 getMin()/getMax() 的边界值行为——它们不是 0 或 null,而是无穷大,直接用于前端展示或比较前,最好显式判断 stats.getCount() == 0。


















