Search code examples
javajava-8java-stream

Java stream. Sum two fields in a stream of objects


I have something like this:

Integer totalIncome = carDealer.getBrands().stream().mapToInt(brand -> brand.getManufacturer().getIncome()).sum();
Integer totalOutcome = carDealer.getBrands().stream().mapToInt(brand -> brand.getManufacturer().getOutcome()).sum();

How could I write that in one stream ? to collect f.e. Pair<Integer, Integer> with totalIncome and totalOutcome ?

EDITED:

Thank you guys for your comments, answers, and involvment. I would have a question about different approach to that problem using streams. What do you think about that:

final IncomeAndOutcome incomeAndOutcome = carDealer.getBrands()
                    .stream()
                    .map(Brand::getManufacturer)
                    .map(IncomeAndOutcome::of)
                    .reduce(IncomeAndOutcome.ZERO, IncomeAndOutcome::sum);

static class IncomeAndOutcome {

    private static final IncomeAndOutcome ZERO = of(0, 0);

    @Getter
    private final int income;

    @Getter
    private final int outcome;

    public static IncomeAndOutcome of(final int income, final int outcome) {
        return new IncomeAndOutcome(income, outcome);
    }

    public static IncomeAndOutcome of(final Manufacturer manufacturer) {
        return new IncomeAndOutcome(manufacturer.getIncome(), manufacturer.getOutcome());
    }

    IncomeAndOutcome(final int income, final int outcome) {
        this.income = income;
        this.outcome = outcome;
    }

    IncomeAndOutcome sum(final IncomeAndOutcome incomeAndOutcome) {
        return of(this.income + incomeAndOutcome.getIncome(), this.outcome + incomeAndOutcome.getOutcome());
    }
}

Solution

  • Without measuring correctly - everything is guessing. The only argument I do agree with is about readability - this is hardly the case here; but in case you wanted to know this for academic purposes, you can do it:

    int[] result = carDealer.getBrands()
             .stream()
             .map(brand -> new int[]{brand.getManufacturer().getIncome(),
                                     brand.getManufacturer().getOutcome()})
             .collect(Collector.of(
                        () -> new int[2],
                        (left, right) -> {
                            left[0] += right[0];
                            left[1] += right[1];
                        },
                        (left, right) -> {
                            left[0] += right[0];
                            left[1] += right[1];
                            return left;
                        }));