Статья

Суммирование чисел с помощью стримов Java

В этом коротком руководстве мы рассмотрим различные способы вычисления суммы целых чисел с помощью Stream API.
Для простоты в наших примерах мы будем использовать Integer числа, однако можно применить те же методы и к типам Long и Double.

Использование Stream.reduce()

Stream.reduce() – это терминальная операция, которая выполняет сокращение элементов в стриме.
Операция применяет бинарный оператор (аккумулятор) к каждому элементу в стриме, где первый операнд является возвращаемым значением предыдущего элемента, а второй – текущим элементом стрима.
В первом примере функция-аккумулятор представляет собой лямбда-выражение, которое складывает два целых значения и возвращает также целое значение:
List<Integer> ints = Arrays.asList(1, 2, 3, 4);
Integer sum = ints.stream()
  .reduce(0, (a, b) -> a + b);
Таким же образом мы можем использовать статический Java-метод Integer::sum:
List<Integer> ints = Arrays.asList(1, 2, 3, 4);
Integer sum = ints.stream()
  .reduce(0, Integer::sum);
Или мы можем определить и использовать наш пользовательский метод:
public class MathUtils {

    public static int add(int a, int b) {
        return a + b;
    }
}

//...

List<Integer> ints = Arrays.asList(1, 2, 3, 4);
Integer sum = ints.stream()
  .reduce(0, MathUtils::add);

Использование Stream.collect()

Второй способ вычисления суммы списка целых чисел заключается в использовании терминальной операции collect():
List<Integer> ints = Arrays.asList(1, 2, 3, 4);
Integer sum = ints.stream()
  .collect(Collectors.summingInt(Integer::intValue));
Аналогично, класс Collectors предоставляет методы summingLong() и summingDouble() для вычисления сумм коллекций типов Long и Double соответственно.

Использование IntStream.sum()

Stream API предоставляет нам промежуточную операцию mapToInt(), которая преобразует наш стрим в объект IntStream.
Этот метод принимает mapper в качестве параметра, который он использует для выполнения преобразования, затем мы можем вызвать метод sum() для вычисления суммы элементов стрима.
Давайте посмотрим на короткий пример того, как мы можем его использовать:
List<Integer> ints = Arrays.asList(1, 2, 3, 4);
Integer sum = ints.stream()
  .mapToInt(Integer::intValue)
  .sum();
Таким же образом мы можем использовать методы mapToLong() и mapToDouble() для вычисления сумм коллекций типов Long и Double соответственно.

Использование Stream#sum с map

Чтобы вычислить сумму значений структуры данных Map<Object, Integer>, сначала мы создадим стрим из значений этого map. Далее применим один из методов, которые мы использовали ранее. Например, IntStream.sum():
Integer sum = map.values()
  .stream()
  .mapToInt(Integer::valueOf)
  .sum();

Использование Stream#sum с объектами

Давайте представим, что у нас есть список объектов и мы хотим вычислить сумму всех значений выбранного поля этих объектов.
Например:
public class Item {

    private int id;
    private Integer price;

    public Item(int id, Integer price) {
        this.id = id;
        this.price = price;
    }

    // стандартные геттеры и сеттеры

}
Далее давайте представим, что мы хотим рассчитать итоговую цену всех товаров из следующего списка:
Item item1 = new Item(1, 5);
Item item2 = new Item(2, 10);
Item item3 = new Item(3, 15);
Item item4 = new Item(4, 20);
        
List<Item> items = Arrays.asList(item1, item2, item3, item4);
Чтобы вычислить сумму, используя методы, показанные в предыдущих примерах, нам нужно вызвать метод map() для преобразования нашего стрима в стрим целых чисел.

Можно использовать Stream.reduce(), Stream.collect() и IntStream.sum() для вычисления суммы:
Integer sum = items.stream()
  .map(x -> x.getPrice())
  .reduce(0, ArithmeticUtils::add);

sum = items.stream()
  .map(x -> x.getPrice())
  .reduce(0, Integer::sum);

sum = items.stream()
  .map(item -> item.getPrice())
  .reduce(0, (a, b) -> a + b);

sum = items.stream()
  .map(x -> x.getPrice())
  .collect(Collectors.summingInt(Integer::intValue));

sum = items.stream()
  .mapToInt(x -> x.getPrice())
  .sum();

Заключение

В этой статье мы рассмотрели несколько методов вычисления суммы списка целых чисел с помощью Stream API. Мы также использовали эти методы для вычисления суммы значений выбранного поля списка объектов и суммы значений map.
java