Home | | **Object Oriented Programming** | | **The Complete Reference Java** | | **Internet Programming** | | **Web Programming** | Reduction Operations - Java Stream API

Consider the min( ) and max( ) methods in the preceding example program. Both are terminal operations that return a result based on the elements in the stream.

**Reduction
Operations**

Consider the **min( )** and **max( )** methods in the preceding example program. Both are terminal
operations that return a result based on the elements in the stream. In the
language of the stream API, they represent *reduction
operations* because each reduces a stream to a single value—in this case,
the minimum and maximum. The stream API refers to these as *special case* reductions because they perform a specific function.
In addition to **min( )** and **max( )**, other special case reductions
are also available, such as **count( )**,
which counts the number of elements in a stream. However, the stream API
generalizes this concept by providing the **reduce(
) **method. By using** reduce( )**,
you can return a value from a stream based on any** **arbitrary criteria. By definition, all reduction operations are
terminal operations.

**Stream **defines three versions of**
reduce( )**. The two we will use first are shown here:** **Optional<T> reduce(BinaryOperator<T> *accumulator*)

T reduce(T *identityVal*, BinaryOperator<T> *accumulator*)

The first form returns an
object of type **Optional**, which
contains the result. The second form returns an object of type **T** (which is the element type of the
stream). In both forms, *accumulator *is
a function that operates on two values and produces a result. In the second* *form, *identityVal* is a value such that an accumulator operation involving
*identityVal* and any element of the
stream yields that element, unchanged. For example, if the operation is addition,
then the identity value will be 0 because 0 + x is x. For multiplication, the
value will be 1, because 1 * x is x.

**BinaryOperator **is a functional interface declared in** java.util.function **that extends the** BiFunction **functional interface.** BiFunction **defines this abstract method:

R apply(T *val*, U *val2*)

Here, **R** specifies the result type, **T**
is the type of the first operand, and **U**
is the type of second operand. Thus, **apply(
)** applies a function to its two operands (*val* and *val2*) and returns
the result. When **BinaryOperator**
extends **BiFunction**, it specifies the
same type for all the type parameters. Thus, as it relates to **BinaryOperator**, **apply( )** looks like this:

T apply(T *val*, T *val2*)

Furthermore, as it relates to
**reduce( )**, *val* will contain the previous result and *val2* will contain the next element. In its first invocation, *val* will contain either the identity
value or the first element, depending on which version of **reduce( )** is used.

It is important to understand
that the accumulator operation must satisfy three constraints. It must be

Stateless

Non-interfering

Associative

As explained earlier, *stateless* means that the operation does
not rely on any state information. Thus, each element is processed
independently. *Non-interfering* means
that the data source is not modified by the operation. Finally, the operation
must be *associative*. Here, the term *associative *is used in its normal,
arithmetic sense, which means that, given an associative* *operator used in a sequence of operations, it does not matter which
pair of operands are processed first. For example,

(10 * 2) * 7

yields the same result as 10
* (2 * 7)

Associativity is of
particular importance to the use of reduction operations on parallel streams,
discussed in the next section.

The following program
demonstrates the versions of **reduce( )**
just described:

// Demonstrate the reduce() method.

import java.util.*;

import java.util.stream.*;

class StreamDemo2 {

public static void main(String[] args) {

// Create a list of Integer values.

ArrayList<Integer> myList = new
ArrayList<>( );

myList.add(7);

myList.add(18);

myList.add(10);

myList.add(24);

myList.add(17);

myList.add(5);

//Two ways to obtain the integer product of the
elements

//in myList by use of reduce().

Optional<Integer> productObj =
myList.stream().reduce((a,b) -> a*b); if(productObj.isPresent())

System.out.println("Product as Optional:
" + productObj.get());

int product = myList.stream().reduce(1, (a,b)
-> a*b); System.out.println("Product as int: " + product);

}

}

As the output here shows,
both uses of **reduce( )** produce the
same result:

Product as Optional: 2570400

Product as int: 2570400

In the program, the first
version of **reduce( )** uses the lambda
expression to produce a product of two values. In this case, because the stream
contains **Integer** values, the **Integer** objects are automatically
unboxed for the multiplication and reboxed to return the result. The two values
represent the current value of the running result and the next element in the
stream. The final result is returned in an object of type **Optional**. The value is obtained by calling **get( )** on the returned object.

In the second version, the
identity value is explicitly specified, which for multiplication is 1. Notice
that the result is returned as an object of the element type, which is **Integer** in this case.

Although simple reduction
operations such as multiplication are useful for examples, reductions are not
limited in this regard. For example, assuming the preceding program, the
following obtains the product of only the even values:

int evenProduct = myList.stream().reduce(1,
(a,b) -> { if(b%2 == 0) return a*b; else return a;

});

Pay special attention to the
lambda expression. If **b** is even,
then **a** * **b** is returned. Otherwise, **a **is
returned. This works because** a **holds
the current result and** b **holds the
next element,** **as explained earlier.

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail

**Related Topics **

Copyright © 2018-2021 BrainKart.com; All Rights Reserved. (BS) Developed by Therithal info, Chennai.