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

1. Въведение

В този бърз урок ще покажем различни начини за изчисляване на сумата от цели числа, използвайки Stream API .

За по-голяма простота ще използваме цели числа в нашите примери. Въпреки това можем да приложим същите методи и за удължаване и удвояване.

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

Stream.reduce () е терминална операция, която извършва намаляване на елементите на потока .

Той прилага двоичен оператор (акумулатор) към всеки елемент в потока, където първият операнд е връщаната стойност на предишното приложение, а вторият е текущият елемент на потока.

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

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

По същия начин можем да използваме вече съществуващ метод на Java :

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

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

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

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

По подобен начин класът Collectors осигурява методите summingLong () и summingDouble () за изчисляване на сумите на longs и double .

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

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

Този метод приема mapper като параметър, който използва за преобразуване, след което можем да извикаме метода sum () , за да изчислим сумата от елементите на потока.

Нека да видим бърз пример за това как можем да го използваме:

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

По същия начин можем да използваме методите mapToLong () и mapToDouble () , за да изчислим съответно сумите на лонговете и двойниците.

5. Използване на поток # сума с карта

За да изчислим сумата от стойности на структура от данни на Map , първо създаваме поток от стойностите на тази карта , след което прилагаме един от методите, които използвахме преди.

Например, като използвате IntStream.sum () :

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

6. Използване на поточна # сума с обекти

Нека си представим, че имаме списък с обекти и че искаме да изчислим сумата от всички стойности на дадено поле на тези обекти.

Например:

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 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. Използване на поток # сума с низ

Да предположим, че имаме обект 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.