Перейти к основному содержимому

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

· 4 мин. чтения

1. Введение

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

Для простоты мы будем использовать в наших примерах целые числа; тем не менее, мы можем применить те же методы к longs и double.

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

Stream.reduce() — это терминальная операция, выполняющая сокращение элементов потока .

Он применяет бинарный оператор (аккумулятор) к каждому элементу в потоке, где первый операнд — это возвращаемое значение предыдущего приложения, а второй — текущий элемент потока.

В первом методе использования метода reduce() функция-аккумулятор представляет собой лямбда-выражение, которое складывает два целочисленных значения и возвращает целочисленное значение:

List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
Integer sum = integers.stream()
.reduce(0, (a, b) -> a + b);

Точно так же мы можем использовать уже существующий метод Java :

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

Или мы можем определить и использовать наш собственный метод:

public class ArithmeticUtils {

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

Затем мы можем передать эту функцию в качестве параметра методу reduce() :

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

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

Второй метод вычисления суммы списка целых чисел заключается в использовании терминальной операции collect() :

List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
Integer sum = integers.stream()
.collect(Collectors.summingInt(Integer::intValue));

Точно так же класс Collectors предоставляет методы summingLong() и summingDouble() для вычисления сумм значений long и double соответственно.

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

Stream API предоставляет нам промежуточную операцию mapToInt() , которая преобразует наш поток в объект IntStream .

Этот метод принимает преобразователь в качестве параметра, который он использует для преобразования, затем мы можем вызвать метод sum() для вычисления суммы элементов потока.

Давайте посмотрим на краткий пример того, как мы можем его использовать:

List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
Integer sum = integers.stream()
.mapToInt(Integer::intValue)
.sum();

Точно так же мы можем использовать методы mapToLong() и mapToDouble() для вычисления сумм длинных и двойных значений соответственно.

5. Использование Stream#sum с картой

Чтобы вычислить сумму значений структуры данных Map<Object, Integer> , сначала мы создаем поток из значений этой карты. Затем мы применяем один из методов, которые мы использовали ранее.

Например, используя IntStream.sum() :

Integer sum = map.values()
.stream()
.mapToInt(Integer::valueOf)
.sum();

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

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

Например:

public class Item {

private int id;
private Integer price;

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

// Standard getters and setters
}

Далее давайте представим, что мы хотим рассчитать общую стоимость всех элементов следующего списка:

Item item1 = new Item(1, 10);
Item item2 = new Item(2, 15);
Item item3 = new Item(3, 25);
Item item4 = new Item(4, 40);

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);
Integer sum = items.stream()
.map(x -> x.getPrice())
.reduce(0, Integer::sum);
Integer sum = items.stream()
.map(item -> item.getPrice())
.reduce(0, (a, b) -> a + b);
Integer sum = items.stream()
.map(x -> x.getPrice())
.collect(Collectors.summingInt(Integer::intValue));
items.stream()
.mapToInt(x -> x.getPrice())
.sum();

7. Использование Stream#sum со строкой

Предположим, что у нас есть объект String , содержащий несколько целых чисел.

Чтобы вычислить сумму этих целых чисел, сначала нам нужно преобразовать эту строку в массив. Далее нам нужно отфильтровать нецелочисленные элементы и, наконец, преобразовать оставшиеся элементы этого массива в числа.

Давайте посмотрим на все эти шаги в действии:

String string = "Item1 10 Item2 25 Item3 30 Item4 45";

Integer sum = Arrays.stream(string.split(" "))
.filter((s) -> s.matches("\\d+"))
.mapToInt(Integer::valueOf)
.sum();

8. Заключение

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

Как всегда, полный код доступен на GitHub .