Senthil Senthil - 7 months ago 37
Java Question

How to collect two sum from a stream in Java 8

class Stock{
double profit;
double profitPercentage;
public double getProfit(){
return profit;
public double getProfitPercentage(){
return profitPercentage;
List<Stock> stocks = getAllStocks();;;

I could not find out way to do in single pass of stream. Any help or pointer would be good.


The straight-forward way is to create a custom collector class.

public class StockStatistics {

    private DoubleSummaryStatistics profitStat = new DoubleSummaryStatistics();
    private DoubleSummaryStatistics profitPercentageStat = new DoubleSummaryStatistics();

    public void accept(Stock stock) {

    public StockStatistics combine(StockStatistics other) {
        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;


This class serves as a wrapper around two DoubleSummaryStatistics. It delegates to them each time an element is accepted. In your case, since you're only interested in the sum, you could even use a Collectors.summingDouble instead of DoubleSummaryStatistics. Also, it returns the two statistics with getProfitStat and getProfitPercentageStat; alternatively, you could add a finisher operation that would return a double[] containing only both sums.

Then, you can use

StockStatistics stats =;

A more generic way is to create a collector capable of pairing other collectors. You can use the pairing collector written in this answer and, also available in the StreamEx library.

double[] sums =
    (sum1, sum2) -> new double[] { sum1, sum2 }

The sum of the profit will be in sums[0] and the sum of the profit percentage will be in sums[1]. In this snippet, only the sums are kept and not the whole stats.