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:

  • the key is the elements to group by
  • and the value is the elements grouped in a collection

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

  • Grouping by gender (Ref)
Map<Person.Sex, List<Person>> byGender =
    roster
        .stream()
        .collect(
            Collectors.groupingBy(Person::getGender));
  • retrieves the names of each member in the collection roster and groups them by gender (Ref)
Map<Person.Sex, List<String>> namesByGender =
    roster
        .stream()
        .collect(
            Collectors.groupingBy(
                Person::getGender,                      
                Collectors.mapping(
                    Person::getName,
                    Collectors.toList())));
  • to compute the set of last names of people in each city, where the city names are sorted (ref
Map<City, Set<String>> namesByCity = people
    .stream()
    .collect(groupingBy(
        Person::getCity, 
        TreeMap::new, // The constructor
        mapping(Person::getLastName, toSet())
        ));

With reduce operation

  • Retrieves the total age of members of each gender
Map<Person.Sex, Integer> totalAgeByGender =
    roster
        .stream()
        .collect(
            Collectors.groupingBy(
                Person::getGender,                      
                Collectors.reducing(
                    0,
                    Person::getAge,
                    Integer::sum)));
  • retrieves the average age of members of each gender (Ref)
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) ) ));
  • to calculate the longest last name of residents in each city:
Comparator<String> byLength = Comparator.comparing(String::length);
Map<City, String> longestLastNameByCity = people
    .stream()
    .collect( groupingBy(
        Person::getCity,
        reducing(Person::getLastName, BinaryOperator.maxBy(byLength))
        )
    );

Powered by ComboStrap