'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 1:[1]

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;
                    }));

Solution 2:[2]

This will give you total of income & outcome. Here 1st argument of reduce() is the identity. If you are not specifying that reduce() function will give optional value.

Pair<Integer, Integer> result = carDealer.getBrands()
                    .stream()
                    .map(brand -> Pair.of(brand.getManufacturer().getIncome(), brand.getManufacturer().getOutcome()))
                    .reduce(Pair.of(0, 0), (pair1, pair2) -> Pair.of(pair1.getFirst() + pair2.getFirst(), pair1.getSecond() + pair2.getSecond()));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 DharmanBot