直接的方法是创建一个自定义收集器类。
public class StockStatistics {
private DoubleSummaryStatistics profitStat = new DoubleSummaryStatistics();
private DoubleSummaryStatistics profitPercentageStat = new DoubleSummaryStatistics();
public void accept(Stock stock) {
profitStat.accept(stock.getProfit());
profitPercentageStat.accept(stock.getProfitPercentage());
}
public StockStatistics combine(StockStatistics other) {
profitStat.combine(other.profitStat);
profitPercentageStat.combine(other.profitPercentageStat);
return this;
}
public static Collector<Stock, ?, StockStatistics> collector() {
return Collector.of(StockStatistics::new, StockStatistics::accept, StockStatistics::combine);
}
public DoubleSummaryStatistics getProfitStat() {
return profitStat;
}
public DoubleSummaryStatistics getProfitPercentageStat() {
return profitPercentageStat;
}
}
这个类是两个DoubleSummaryStatistics的包装器。每次接受一个元素时,它会委托给它们。在您的情况下,由于您只对总和感兴趣,您甚至可以使用Collectors.summingDouble而不是DoubleSummaryStatistics。此外,它使用getProfitStat和getProfitPercentageStat返回两个统计信息;或者,您可以添加一个完成操作,该操作将返回仅包含两个总和的double[]。
然后,您可以使用:
StockStatistics stats = stocks.stream().collect(StockStatistics.collector());
System.out.println(stats.getProfitStat().getSum());
System.out.println(stats.getProfitPercentageStat().getSum());
一种更通用的方法是创建一个收集器,能够将其他收集器成对配对。您可以使用 此答案中编写的 pairing
收集器,也可在 StreamEx 库中找到。
double[] sums = stocks.stream().collect(MoreCollectors.pairing(
Collectors.summingDouble(Stock::getProfit),
Collectors.summingDouble(Stock::getProfitPercentage),
(sum1, sum2) -> new double[] { sum1, sum2 }
));
利润总和将存储在
sums [0]
中,利润百分比总和将存储在
sums [1]
中。在此片段中,仅保留总和而不是整个统计数据。
Collectors.summarizingDouble
,而是编写自己的收集器。返回类型将不是单个double值,而是包含两个总和的POJO或Tuple2。 - Matthias J. Sax