Java stream reduce пример

Java stream reduce пример

Метод reduce выполняет терминальные операции сведения, возвращая некоторое значение — результат операции. Он имеет следующие формы:

Optional reduce(BinaryOperator accumulator) T reduce(T identity, BinaryOperator accumulator) U reduce(U identity, BiFunction accumulator, BinaryOperator combiner)

Первая форма возвращает результат в виде объекта Optional . Например, вычислим произведение набора чисел:

import java.util.stream.Stream; import java.util.Optional; public class Program < public static void main(String[] args) < StreamnumbersStream = Stream.of(1,2,3,4,5,6); Optional result = numbersStream.reduce((x,y)->x*y); System.out.println(result.get()); // 720 > >

Объект BinaryOperator представляет функцию, которая принимает два элемента и выполняет над ними некоторую операцию, возвращая результат. При этом метод reduce сохраняет результат и затем опять же применяет к этому результату и следующему элементу в наборе бинарную операцию. Фактически в данном случае мы получим результат, который будет равен: n1 op n2 op n3 op n4 op n5 op n6 , где op — это операция (в данном случае умножения), а n1, n2, . — элементы из потока.

Затем с помощью метода get() мы можем получить собственно результат вычислений: result.get()

Или еще один пример — объединение слов в предложение:

Stream wordsStream = Stream.of("мама", "мыла", "раму"); Optional sentence = wordsStream.reduce((x,y)->x + " " + y); System.out.println(sentence.get());

Вторая версия метода reduce() принимает два параметра:

T reduce(T identity, BinaryOperator accumulator)

Первый параметр — T identity — элемент, который предоставляет начальное значение для функции из второго параметра, а также предоставляет значение по умолчанию, если поток не имеет элементов.

Второй параметр — BinaryOperator accumulator , как и первая форма метода reduce, представляет ассоциативную функцию, которая запускается для каждого элемента в потоке и принимает два параметра. Первый параметр представляяет промежуточный результат функции, а второй параметр — следующий элемент в потоке. Фактически код этого метода будет равноценен следующей записи:

T result = identity; for (T element : this stream) result = accumulator.apply(result, element) return result;

То есть при первом вызове функция accumulator в качестве первого параметра принимает значение identity, а в качестве второго параметра — первый элемент потока. При втором вызове первым параметром служит результат первого вызова функции accumulator, а вторым параметром — второй элемент в потоке и так далее. Например:

Stream numberStream = Stream.of(-4, 3, -2, 1); int identity = 1; int result = numberStream.reduce(identity, (x,y)->x * y); System.out.println(result); // 24

Фактически здесь выполняется следующая цепь операций: identity op n1 op n2 op n3 op n4.

В предыдущих примерах тип возвращаемых объектов совпадал с типом элементов, которые входят в поток. Однако это не всегда удобно. Возможно, мы захотим возвратить результат, тип которого отличается от типа объектов потока. Например, пусть у нас есть следующий класс Phone, представляющий телефон:

class Phone < private String name; private int price; public Phone(String name, int price)< this.name=name; this.price=price; >public String getName() < return name; >public int getPrice() < return price; >>

И мы хотим найти сумму цен тех телефонов, у которых цена меньше определенного значения. Для этого используем третью версию метода reduce:

Stream phoneStream = Stream.of(new Phone("iPhone 6 S", 54000), new Phone("Lumia 950", 45000), new Phone("Samsung Galaxy S 6", 40000), new Phone("LG G 4", 32000)); int sum = phoneStream.reduce(0, (x,y)-> < if(y.getPrice()<50000) return x + y.getPrice(); else return x + 0; >, (x, y)->x+y); System.out.println(sum); // 117000

Опять же здесь в качестве первого параметра идет значение по умолчанию — 0. Второй параметр производит бинарную операцию, которая получает промежуточное значение — суммарную цену текущего и предыдущего телефонов. Третий параметр представляет бинарную операцию, которая суммирует все промежуточные вычисления.

Источник

Interface Stream

A sequence of elements supporting sequential and parallel aggregate operations. The following example illustrates an aggregate operation using Stream and IntStream :

 int sum = widgets.stream() .filter(w -> w.getColor() == RED) .mapToInt(w -> w.getWeight()) .sum(); 

In this example, widgets is a Collection . We create a stream of Widget objects via Collection.stream() , filter it to produce a stream containing only the red widgets, and then transform it into a stream of int values representing the weight of each red widget. Then this stream is summed to produce a total weight.

In addition to Stream , which is a stream of object references, there are primitive specializations for IntStream , LongStream , and DoubleStream , all of which are referred to as «streams» and conform to the characteristics and restrictions described here.

To perform a computation, stream operations are composed into a stream pipeline. A stream pipeline consists of a source (which might be an array, a collection, a generator function, an I/O channel, etc), zero or more intermediate operations (which transform a stream into another stream, such as filter(Predicate) ), and a terminal operation (which produces a result or side-effect, such as count() or forEach(Consumer) ). Streams are lazy; computation on the source data is only performed when the terminal operation is initiated, and source elements are consumed only as needed.

A stream implementation is permitted significant latitude in optimizing the computation of the result. For example, a stream implementation is free to elide operations (or entire stages) from a stream pipeline — and therefore elide invocation of behavioral parameters — if it can prove that it would not affect the result of the computation. This means that side-effects of behavioral parameters may not always be executed and should not be relied upon, unless otherwise specified (such as by the terminal operations forEach and forEachOrdered ). (For a specific example of such an optimization, see the API note documented on the count() operation. For more detail, see the side-effects section of the stream package documentation.)

Collections and streams, while bearing some superficial similarities, have different goals. Collections are primarily concerned with the efficient management of, and access to, their elements. By contrast, streams do not provide a means to directly access or manipulate their elements, and are instead concerned with declaratively describing their source and the computational operations which will be performed in aggregate on that source. However, if the provided stream operations do not offer the desired functionality, the BaseStream.iterator() and BaseStream.spliterator() operations can be used to perform a controlled traversal.

A stream pipeline, like the «widgets» example above, can be viewed as a query on the stream source. Unless the source was explicitly designed for concurrent modification (such as a ConcurrentHashMap ), unpredictable or erroneous behavior may result from modifying the stream source while it is being queried.

  • must be non-interfering (they do not modify the stream source); and
  • in most cases must be stateless (their result should not depend on any state that might change during execution of the stream pipeline).

Such parameters are always instances of a functional interface such as Function , and are often lambda expressions or method references. Unless otherwise specified these parameters must be non-null.

A stream should be operated on (invoking an intermediate or terminal stream operation) only once. This rules out, for example, «forked» streams, where the same source feeds two or more pipelines, or multiple traversals of the same stream. A stream implementation may throw IllegalStateException if it detects that the stream is being reused. However, since some stream operations may return their receiver rather than a new stream object, it may not be possible to detect reuse in all cases.

Streams have a BaseStream.close() method and implement AutoCloseable . Operating on a stream after it has been closed will throw IllegalStateException . Most stream instances do not actually need to be closed after use, as they are backed by collections, arrays, or generating functions, which require no special resource management. Generally, only streams whose source is an IO channel, such as those returned by Files.lines(Path) , will require closing. If a stream does require closing, it must be opened as a resource within a try-with-resources statement or similar control structure to ensure that it is closed promptly after its operations have completed.

Stream pipelines may execute either sequentially or in parallel. This execution mode is a property of the stream. Streams are created with an initial choice of sequential or parallel execution. (For example, Collection.stream() creates a sequential stream, and Collection.parallelStream() creates a parallel one.) This choice of execution mode may be modified by the BaseStream.sequential() or BaseStream.parallel() methods, and may be queried with the BaseStream.isParallel() method.

Источник

Java 8 Stream reduce() Example

On this page we will provide Java 8 Stream reduce() example. Stream reduce() performs a reduction on the elements of the stream. It uses identity and accumulator function for reduction. In parallel processing we can pass combiner function as additional parameter to this method. Stream reduce() can be used to get the sum of numbers stored in collection. It can also concatenate the string data stored in collection with given separator. Stream reduce() method can perform many more reducing task as required. We are providing here some examples.

Contents

Stream.reduce() with Accumulator

Here we will pass BinaryOperator as accumulator. In case of numeric BinaryOperator , the start value will be 0. In case of string, the start value will be a blank string.

The method will return Optional instance. Find the example.
ReduceDemo1.java

package com.concretepage; import java.util.Arrays; public class ReduceDemo1 < public static void main(String[] args) < int[] array = ; Arrays.stream(array).reduce((x,y) -&gt x+y).ifPresent(s -&gt System.out.println(s)); Arrays.stream(array).reduce(Integer::sum).ifPresent(s -&gt System.out.println(s)); Arrays.stream(array).reduce(StatisticsUtility::addIntData).ifPresent(s -&gt System.out.println(s)); > >
package com.concretepage; public class StatisticsUtility < public static int addIntData(int num1, int num2) < return num1 + num2; >>

Stream.reduce() with Identity and Accumulator

Here we will use an identity and accumulator. We will pass the identity as start value.

reduce(T identity, BinaryOperator&ltT&gt accumulator)
Find the example.
ReduceDemo2.java

package com.concretepage; import java.util.Arrays; public class ReduceDemo2 < public static void main(String[] args) < int[] array = ; //Set start value. Result will be start value + sum of array. int startValue = 100; int sum = Arrays.stream(array).reduce(startValue, (x,y) -&gt x+y); System.out.println(sum); sum = Arrays.stream(array).reduce(startValue, Integer::sum); System.out.println(sum); sum = Arrays.stream(array).reduce(startValue, StatisticsUtility::addIntData); System.out.println(sum); > >

Stream.reduce() with Identity, Accumulator and Combiner

Here we will pass three arguments identity, accumulator and combiner in reduce() method. The identity value must be an identity for the combiner function. This method with three arguments is used in parallel processing. Combiner works with parallel stream only, otherwise there is nothing to combine.

reduce(U identity, BiFunction&ltU,? super T,U&gt accumulator, BinaryOperator&ltU&gt combiner)

Find the example.
ReduceDemo3.java

package com.concretepage; import java.util.Arrays; import java.util.List; public class ReduceDemo3 < public static void main(String[] args) < List&ltInteger&gt list2 = Arrays.asList(5, 6, 7); int res = list2.parallelStream().reduce(1, (s1, s2) -&gt s1 * s2, (p, q) -&gt p * q); System.out.println(res); >>

Reduce List and Array into a String

package com.concretepage; import java.util.Arrays; import java.util.List; public class ReduceToString < public static void main(String[] args) < //Reduce Array to String. String[] array = ; Arrays.stream(array).reduce((x, y) -&gt x +"," + y) .ifPresent(s -&gt System.out.println("Array to String: "+ s)); //Reduce List to String. List&ltString&gt list = Arrays.asList("Mohan", "Sohan", "Mahesh"); list.stream().reduce((x, y) -&gt x +"," + y) .ifPresent(s -&gt System.out.println("List to String: "+ s)); > >
Array to String: Mohan,Sohan,Mahesh List to String: Mohan,Sohan,Mahesh

Reduce List and Array into Sum

package com.concretepage; import java.util.Arrays; import java.util.List; public class ReduceToSum < public static void main(String[] args) < //Reduce Array to sum. int[] array = ; int sum = Arrays.stream(array).reduce(0, (x, y) -&gt x + y); System.out.println("Sum of Array: "+ sum); //Reduce List to sum. List&ltInteger&gt list = Arrays.asList(30, 10, 20, 40); sum = list.stream().reduce(0, (x, y) -&gt x + y); System.out.println("Sum of List: "+ sum); > >
Sum of Array: 100 Sum of List: 100

Источник

Читайте также:  Charting libraries in javascript
Оцените статью