Java - Stream Group Operation

Introduction

The groupingBy() method from the Collectors class groups the data before collecting them in a Map.

It is similar to using a "group by" clause in SQL.

The groupingBy() method is overloaded and it has three versions:

groupingBy(Function<? super T,? extends K> classifier)

groupingBy(Function<? super T,? extends K> classifier,  
           Collector<? super T,A,D> downstream)

groupingBy(Function<? super T,? extends K> classifier, 
           Supplier<M> mapFactory,
           Collector<? super T,A,D> downstream)

The third version can specify a Supplier that is used as the factory to get the Map object.

In the first two versions, the collector takes care of creating the Map object for you.

A classifier that is a function to generate the keys in the map.

A collector that performs a reduction operation on the values associated with each key.

The following code collects the list of people by gender:

Map<Person.Gender, List<Person>> personsByGender =
        Person.persons()
              .stream()
              .collect(Collectors.groupingBy(Person::getGender));

groupingBy() method that lets you perform a reduction operation on the values of each key.

To group people by gender and count the number of people in each group.

The counting() method of the Collectors class returns a Collector to count the number of elements in a stream.

Map<Person.Gender, Long> countByGender =
        Person.persons()
              .stream()
              .collect(Collectors.groupingBy(Person::getGender, Collectors.counting()));

To list a person's name by gender, use the mapping() method from Collectors class.

The signature of the mapping() method is

mapping(Function<? super T,? extends U> mapper, 
        Collector<? super U,A,R> downstream)

The following code groups the names of person by gender:

Map<Person.Gender, String> namesByGender =
    Person.persons()
          .stream()
          .collect(Collectors.groupingBy(Person::getGender,
                   Collectors.mapping(Person::getName, Collectors.joining(", "))));

The code collects the names for a group in a comma-separated String.

To collect the names in a List, use the collector returned by the toList() method:

Map<Person.Gender, List<String>> namesByGender =
        Person.persons()
              .stream()
              .collect(Collectors.groupingBy(Person::getGender,
                  Collectors.mapping(Person::getName, Collectors.toList())));

Related Topics