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.