groupingBy and partitioningBy
Build grouped reports in one pass with groupingBy, partitioningBy and downstream collectors.
Open this lesson in the learning hubKey points
groupingBy(classifier)returns a Map of key to List of matching elements. It is the GROUP BY of Java.- The second argument is a downstream collector:
counting(),summingInt(),mapping(),toSet(),maxBy(). - Downstream collectors nest, so you can group by department, map to names, then join them.
partitioningBy(predicate)is a yes/no split. Both thetrueandfalsekeys always exist, even when empty.- Pass a map factory such as
TreeMap::newwhen key order matters.
Example
import java.util.*;
import java.util.stream.*;
public class Main {
record Employee(String name, String dept, int salary) {}
public static void main(String[] args) {
List<Employee> staff = List.of(
new Employee("Ada", "eng", 120),
new Employee("Alan", "eng", 110),
new Employee("Grace", "eng", 130),
new Employee("Edsger", "sales", 90),
new Employee("Barbara", "sales", 95));
Map<String, Long> headcount = staff.stream()
.collect(Collectors.groupingBy(Employee::dept, Collectors.counting()));
Map<String, Integer> payroll = staff.stream()
.collect(Collectors.groupingBy(Employee::dept, Collectors.summingInt(Employee::salary)));
Map<String, List<String>> namesByDept = staff.stream()
.collect(Collectors.groupingBy(Employee::dept, TreeMap::new,
Collectors.mapping(Employee::name, Collectors.toList())));
Map<Boolean, List<String>> split = staff.stream()
.collect(Collectors.partitioningBy(e -> e.salary() >= 110,
Collectors.mapping(Employee::name, Collectors.toList())));
Map<String, Optional<Employee>> topEarner = staff.stream()
.collect(Collectors.groupingBy(Employee::dept,
Collectors.maxBy(Comparator.comparingInt(Employee::salary))));
System.out.println("headcount : " + new TreeMap<>(headcount));
System.out.println("payroll : " + new TreeMap<>(payroll));
System.out.println("names : " + namesByDept);
System.out.println("well paid : " + split.get(true));
System.out.println("the rest : " + split.get(false));
System.out.println("top eng : " + topEarner.get("eng").orElseThrow().name());
}
}
groupingBy plus a downstream collector replaces most report-building loops.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Streams course, and every lesson in it is listed on the Streams contents page.