如何在Java 8中从流中收集两个数字之和

4
class Stock{
   double profit;
   double profitPercentage;
   public double getProfit(){
      return profit;
   }
   public double getProfitPercentage(){
      return profitPercentage;
   }
}
List<Stock> stocks = getAllStocks();
stocks.stream.collect(Collectors.summarizingDouble(Stock:getProfit)).getSum();
stocks.stream.collect(Collectors.summarizingDouble(Stock:getProfitPercentage)).getSum();

我找不到一次流程中完成的方法。任何帮助或指针都会很好。


1
你正在寻找类似于这个的东西:https://dev59.com/910a5IYBdhLWcg3wipJA#30211021。 - Tunaki
链接显示了类似于groupby和sum的内容。对我来说,我需要执行两个字段的总和而不是分组。 - Senthil Kumar Vaithiyanathan
你需要计算所有利润和利润百分比的总和吗? - Tejas Unnikrishnan
是的,确切地说,所有利润的总和和所有利润百分比的总和。 - Senthil Kumar Vaithiyanathan
不要使用Collectors.summarizingDouble,而是编写自己的收集器。返回类型将不是单个double值,而是包含两个总和的POJO或Tuple2。 - Matthias J. Sax
2个回答

2
直接的方法是创建一个自定义收集器类。
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]中。在此片段中,仅保留总和而不是整个统计数据。

0
你可以尝试使用自Java 12起可用的Collectors.teeing
double[] res =
    getAllStocks().stream()
        .collect(
            Collectors.teeing(
                Collectors.summingDouble(Stock::getProfit),
                Collectors.summingDouble(Stock::getProfitPercentage),
                (profitSum, percentageSum) -> new double[] {profitSum, percentageSum}));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接