Streams Reduce
Description
The reduce() operation combines all elements in a stream to produce a single value.
The reduce operation takes two parameters called a seed (initial value) and an accumulator.
The accumulator is a function. If the stream is empty, the seed is the result.
The seed and an element are passed to the accumulator, which returns partial result. And then the partial result and the next element are passed to the accumulator function.
This repeats until all elements are passed to the accumulator. The last value returned from the accumulator is the result of the reduce operation.
The stream-related interfaces contain two methods called reduce() and collect() to perform generic reduce operations.
Methods such as sum(), max(), min(), count(), are defined in IntStream, LongStream, and DoubleStream interfaces.
count() method is available for all types of streams.
The Stream<T> interface contains a reduce() method to perform the reduce operation. The method has three overloaded versions:
T reduce(T identity, BinaryOperator<T> accumulator)
<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
Optional<T> reduce(BinaryOperator<T> accumulator)
Example
The first version of the reduce() method takes an identity and an accumulator as arguments and reduces the stream to a single value of the same type.
import java.util.Arrays;
import java.util.List;
/* w ww .ja v a 2 s. c o m*/
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.reduce(0, Integer::sum);
System.out.println(sum);
}
}
The code above generates the following result.
Example 2
To compute the sum of the incomes of all employee.
import java.time.LocalDate;
import java.time.Month;
import java.util.Arrays;
import java.util.List;
/* www . j av a2 s . c om*/
public class Main {
public static void main(String[] args) {
double sum = Employee.persons()
.stream()
.map(Employee::getIncome)
.reduce(0.0, Double::sum);
System.out.println(sum);
}
}
class Employee {
public static enum Gender {
MALE, FEMALE
}
private long id;
private String name;
private Gender gender;
private LocalDate dob;
private double income;
public Employee(long id, String name, Gender gender, LocalDate dob,
double income) {
this.id = id;
this.name = name;
this.gender = gender;
this.dob = dob;
this.income = income;
}
public double getIncome() {
return income;
}
public static List<Employee> persons() {
Employee p1 = new Employee(1, "Jake", Gender.MALE, LocalDate.of(1971,
Month.JANUARY, 1), 2343.0);
Employee p2 = new Employee(2, "Jack", Gender.MALE, LocalDate.of(1972,
Month.JULY, 21), 7100.0);
Employee p3 = new Employee(3, "Jane", Gender.FEMALE, LocalDate.of(1973,
Month.MAY, 29), 5455.0);
Employee p4 = new Employee(4, "Jode", Gender.MALE, LocalDate.of(1974,
Month.OCTOBER, 16), 1800.0);
Employee p5 = new Employee(5, "Jeny", Gender.FEMALE, LocalDate.of(1975,
Month.DECEMBER, 13), 1234.0);
Employee p6 = new Employee(6, "Jason", Gender.MALE, LocalDate.of(1976,
Month.JUNE, 9), 3211.0);
List<Employee> persons = Arrays.asList(p1, p2, p3, p4, p5, p6);
return persons;
}
}
The code above generates the following result.
Example 3
The second version of the reduce method shown as follows allows us to perform a map operation, followed by a reduce operation.
<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
The third argument is used for combining the partial results when the reduce operation is performed in parallel.
import java.time.LocalDate;
import java.time.Month;
import java.util.Arrays;
import java.util.List;
/*w ww . ja va2 s. c om*/
public class Main {
public static void main(String[] args) {
double sum = Employee.persons()
.stream()
.reduce(0.0, (partialSum, person) -> partialSum + person.getIncome(), Double::sum);
System.out.println(sum);
}
}
class Employee {
public static enum Gender {
MALE, FEMALE
}
private long id;
private String name;
private Gender gender;
private LocalDate dob;
private double income;
public Employee(long id, String name, Gender gender, LocalDate dob,
double income) {
this.id = id;
this.name = name;
this.gender = gender;
this.dob = dob;
this.income = income;
}
public double getIncome() {
return income;
}
public void setIncome(double income) {
this.income = income;
}
public static List<Employee> persons() {
Employee p1 = new Employee(1, "Jake", Gender.MALE, LocalDate.of(1971,
Month.JANUARY, 1), 2343.0);
Employee p2 = new Employee(2, "Jack", Gender.MALE, LocalDate.of(1972,
Month.JULY, 21), 7100.0);
Employee p3 = new Employee(3, "Jane", Gender.FEMALE, LocalDate.of(1973,
Month.MAY, 29), 5455.0);
Employee p4 = new Employee(4, "Jode", Gender.MALE, LocalDate.of(1974,
Month.OCTOBER, 16), 1800.0);
Employee p5 = new Employee(5, "Jeny", Gender.FEMALE, LocalDate.of(1975,
Month.DECEMBER, 13), 1234.0);
Employee p6 = new Employee(6, "Jason", Gender.MALE, LocalDate.of(1976,
Month.JUNE, 9), 3211.0);
List<Employee> persons = Arrays.asList(p1, p2, p3, p4, p5, p6);
return persons;
}
}