Table of Contents

Functional Programming - Group by

About

grouping by is a function that group elements with the same attribute in a apart collection.

The output of a group by operations is normally a map where:

It's a final collect operation that is followed (cascaded) generally with a reduce operation.

Syntax

Map<Classifier, Collection> result = groupingBy(classifier, toCollection());

Example

Only collect Operation

Map<Person.Sex, List<Person>> byGender =
    roster
        .stream()
        .collect(
            Collectors.groupingBy(Person::getGender));
Map<Person.Sex, List<String>> namesByGender =
    roster
        .stream()
        .collect(
            Collectors.groupingBy(
                Person::getGender,                      
                Collectors.mapping(
                    Person::getName,
                    Collectors.toList())));
Map<City, Set<String>> namesByCity = people
    .stream()
    .collect(groupingBy(
        Person::getCity, 
        TreeMap::new, // The constructor
        mapping(Person::getLastName, toSet())
        ));

With reduce operation

Map<Person.Sex, Integer> totalAgeByGender =
    roster
        .stream()
        .collect(
            Collectors.groupingBy(
                Person::getGender,                      
                Collectors.reducing(
                    0,
                    Person::getAge,
                    Integer::sum)));
Map<Person.Sex, Double> averageAgeByGender = roster
    .stream()
    .collect(
        Collectors.groupingBy(
            Person::getGender,                      
            Collectors.averagingInt(Person::getAge)));
Comparator<Person> byHeight = Comparator.comparing(Person::getHeight);
Map<City, Person> tallestByCity = people
    .stream()
    .collect( groupingBy( Person::getCity, reducing(BinaryOperator.maxBy(byHeight) ) ));
Comparator<String> byLength = Comparator.comparing(String::length);
Map<City, String> longestLastNameByCity = people
    .stream()
    .collect( groupingBy(
        Person::getCity,
        reducing(Person::getLastName, BinaryOperator.maxBy(byLength))
        )
    );