What is Collectors.collectingAndThen() in Java?

What is the collectors class?

Collectors is a utility class that provides various implementations of reduction operations such as grouping elements, collecting elements to different collections, summarizing elements according to various criteria, etc. The different functionalities in the Collectors class are usually used as the final operations on streams.

The collectingAndThen() method

collectingAndThen() is a static method of the Collectors class that is used to return a Collector that first applies a collector operation and then applies an additional finishing transformation on the result of the collector operation.

The collectingAndThen() method is defined in the Collectors class. The Collectors class is defined in the java.util.stream package. To import the Collectors class, use the following import statement:

import java.util.stream.Collectors;

Syntax


public static <T, A, R, RR> Collector<T, A, RR> collectingAndThen(Collector<T, A, R> downstream, Function<R, RR> finisher)

Parameters

  • Collector<T, A, R> downstream: The collector to apply.
  • Function<R, RR> finisher: The function to be applied to the final result of the downstream collector.

Return value

The method returns a collector which performs the action of the downstream collector, followed by an additional finishing step.

Code

import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
static class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public static void main(String[] args) {
List<Person> personList = Arrays.asList(new Person("bob", 34), new Person("bob", 43),
new Person("mary", 84), new Person("john", 12), new Person("bob", 22));
System.out.println("list of person objects - " + personList);
Stream<Person> personStream = personList.stream();
Map<String, Set<Integer>> result = personStream.collect(Collectors.groupingBy(p -> p.name,
Collectors.mapping(e -> e.age,
Collectors.collectingAndThen(Collectors.toSet(),
Collections::unmodifiableSet))));
System.out.println("Result of applying collectingAndThen - " + result);
}
}

Explanation

  • Lines 1-4: We import the relevant packages.
  • Lines 8-24: We define a Person class with name and age as the attributes of the class.
  • Lines 27-28: We create a list of the Person objects, called personList, which contains different names and age values.
  • Line 30: We print the personList.
  • Line 32: We create a stream from the personList.
  • Lines 34-37: We first apply the groupingBy reduction with the person name as the group by key. We then perform a mapping of the result of the groupingBy operation to only extract the age value from the grouped Person objects. We then apply the collectingAndThen operation to accumulate the grouped age values to a set. But we need an unmodifiable set. Hence, we apply the unmodifiableSet() method of the Collections class on the set created which returns an unmodifiable view of the set created.
  • Line 39: We print the map of the persons’ names to an unmodifiable set of ages of persons with the same name to the console.

Free Resources