Phase 17 of 20 · Topic 17.4

Advanced Collectors: groupingBy, partitioningBy & Downstreams

1Concept

`java.util.stream.Collectors` enables complex data aggregations: `groupingBy()` groups stream elements into a `Map<K, List<T>>` based on a classification function; `partitioningBy()` partitions elements into a `Map<Boolean, List<T>>`. Downstream collectors (`counting()`, `summingDouble()`, `mapping()`) aggregate grouped values.

2Architecture Diagram

Stream Elements ---> [ Collectors.groupingBy(Employee::getDepartment) ]
                           |                   |
                           v                   v
                   Key: "ENGINEERING"      Key: "FINANCE"
                   List: [Alice, Bob]      List: [Charlie]

3Code Example

Core Java
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class AdvancedCollectorsDemo {
    record Employee(String name, String department, double salary) {}

    public static void main(String[] args) {
        List<Employee> staff = List.of(
            new Employee("Alice", "Engineering", 140000),
            new Employee("Bob", "Engineering", 125000),
            new Employee("Charlie", "Finance", 110000),
            new Employee("Diana", "Finance", 130000)
        );

        // Group by Department and calculate average salary downstream
        Map<String, Double> avgSalaryByDept = staff.stream()
            .collect(Collectors.groupingBy(
                Employee::department,
                Collectors.averagingDouble(Employee::salary)
            ));

        System.out.println("=== Average Salary by Department ===");
        avgSalaryByDept.forEach((dept, avg) -> System.out.printf("%s: $%.2f%n", dept, avg));
    }
}

4Expected Output

=== Average Salary by Department ===
Engineering: $132500.00
Finance: $120000.00

5Key Takeaways

  • `partitioningBy` is optimized for binary boolean conditions.
  • Downstream collectors allow nesting multi-level aggregations in a single pass.
  • Use `Collectors.toUnmodifiableList()` to guarantee immutable output collections.