Reduction OperationsS2C Home « Reduction Operations
Lets start by explaining what reduction operations are! A reduction operation, which is also called a fold in functional programming parlance, takes a sequence of input elements and combines them into a single summary result by repeated application of a combining operation. This could be counting the number of elements in a stream, summing some numbers or finding the maximum value.
We have already encountered the general reduction operations collect()
and reduce()
in previous lessons and we have also used the specialised reduction operation count()
. As you may have inferred from the methods mentioned so far, all reduction operations are terminal.
In this lesson we take a much closer look at all these methods as well other reduction operations methods we haven't used yet. We will start by looking at general reduction operations.
General Reduction Operations Top
There are two general reduction operations, the collect()
method which performs a mutable reduction operation on the elements of this stream, optionally using a Collector
and the reduce()
method which in its simplest form performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional
describing the reduced value, if any.
HashSet<E>
, and elements are incorporated by updating the state of the result rather than by replacing the result
Lets try these methods out! We will be using the Employee
class we created in the Introducing Streams lesson to test against for this purpose.
Following is a TestGeneralReduction
class to demonstrate use of the collect()
and reduce()
methods of the Stream<E>
interface.
package com.server2client;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
/* General reduction operations */
public class TestGeneralReduction {
public static void main(String[] args) {
/* Box and collect to list */
List<Double> doubles = DoubleStream.of(16.2, 8.06, 3.0001, 12, 16.16666)
.boxed()
.collect(Collectors.toList());
System.out.println("Doubles in List collection: " + doubles);
/* Get total salary of all staff */
Optional<Double> salary = Employee.listOfStaff().stream()
.map(Employee::getSalary)
.reduce((e1, e2) -> e1 + e2);
System.out.println("All Employee salary total is " + salary);
/* Get minimum age of all staff */
Optional<Integer> minAge = Employee.listOfStaff().stream()
.map(Employee::getAge)
.reduce(Integer::min);
System.out.println("Youngest member of staff is " + minAge);
/* Get maximum age of all staff */
int maxAge = Employee.listOfStaff().stream()
.map(Employee::getAge)
.reduce(0, Integer::max);
System.out.println("Oldest member of staff is " + maxAge);
}
}
Building and running the TestGeneralReduction
class produces the following output:
Lets go through the code.
We can't store primitives in collections as they are generic so we use the handy boxed()
method to wrap some doubles and use the collect
method along with Collectors.toList()
to store the results in a List<E>
which we print off. We look at collectors in more detail in the Stream Collectors lesson.
In the first use of reduce()
we are using the variant that only takes one parameter, we map and total up the salary of all staff. This could have been more succinctly expressed as .reduce(Double::sum)
In the second use of reduce()
we are again using the variant that only takes one parameter, we map the age and find the youngest employee.
In the third use of reduce()
we are using the variant that takes two parameters, where the first is a default value for when the stream is empty, we map the age and find the eldest employee.
The reason the one parameter variant of reduce()
returns an Optional
is to remove NullPointerException
scenarios.
You won't generally use the reduce()
method, its a lot more efficient to use the aggregate fucntions of the primitive streams DoubleStream
, IntStream
and LongStream
, such as mapToInt()
, which don't require boxing.
Specialised Reduction Operations Top
There are three specialised reduction operations, the count()
method which returns the count of elements in this stream, the min()
method which returns the minimum element of this stream according to the provided Comparator
and the max()
method returns the maximum element of this stream according to the provided Comparator
.
Lets try these methods out! Once again we will be using the Employee
class we created in the Introducing Streams lesson to test against for this purpose.
Following is a TestSpecialisedReduction
class to demonstrate use of the count()
, min()
and max()
methods of the Stream<E>
interface.
package com.server2client;
import java.util.Optional;
import static java.util.Comparator.comparing;
/* Specialised reduction operations */
public class TestSpecialisedReduction {
public static void main(String[] args) {
/* Get count of people over 50 */
long count = Employee.listOfStaff().stream()
.filter(e -> e.getAge() > 50)
.count();
System.out.println("Total employees: " + count);
/* Get minimum salary of all staff */
Optional<Employee> salary = Employee.listOfStaff().stream()
.min(comparing(Employee::getSalary));
System.out.println("Lowest salary: " + salary);
/* Get maximum age of all staff */
Optional<Employee> maxAge = Employee.listOfStaff().stream()
.max(comparing(Employee::getAge));
System.out.println("Oldest member of staff: " + maxAge);
}
}
Building and running the TestSpecialisedReduction
class produces the following output:
First we filter people over 50 and then total them using the count()
method.
Then we get the minimum salary of all staff by comparing salaries using the min()
method which takes a comparator
parameter.
Then we get the maximum age of all staff by comparing ages using the max()
method which takes a comparator
parameter. In this case we are using the comparing()
static method of the Comparator
class.
These methods are more efficient than using reduce()
which could be used instead.
Related Quiz
Streams Quiz 8 - Reduction Operations Quiz
Lesson 8 Complete
In this lesson we looked at stream reduction operations.
What's Next?
In the next lesson we look at stream collectors.