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 .