Java
Summary - Advanced stream
Combine groupingBy, reduce and flatMap to write a sales summarizer.
Summary - Stream advanced
In this group you met five advanced collectors. groupingBy groups elements by a key; partitioningBy splits into two groups; joining merges strings; reduce folds into one value; flatMap flattens nested streams.
Combining them yields powerful solutions. For example, you can pass counting into groupingBy to count per group; or call reduce after flatMap to produce a single total out of nested structures. These combinations keep the code short and readable.
Exercise Count products per category with groupingBy + counting
Create a list of four products (record Product(String name, String category, double price)): two Office, two Grocery. Get a Map<String, Long> with counts per category using Collectors.groupingBy(Product::category, TreeMap::new, Collectors.counting()). Then print each category and its count with forEach.
Show example solution
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
record Product(String name, String category, double price) {}
public class CategoryCounts {
public static void main(String[] args) {
List<Product> products = List.of(
new Product("Pen", "Office", 12.5),
new Product("Notebook", "Office", 25.0),
new Product("Bread", "Grocery", 5.0),
new Product("Milk", "Grocery", 15.0)
);
Map<String, Long> counts = products.stream()
.collect(Collectors.groupingBy(Product::category, TreeMap::new, Collectors.counting()));
counts.forEach((k, v) -> System.out.println(k + ": " + v));
}
}
Which collector when?
Choosing the right collector depends on the question. Use groupingBy to split into categories; partitioningBy to split in two by one condition; joining to merge strings; reduce to produce a single value; flatMap to flatten nested structures.
You can also chain these. Open nested data with flatMap first, then fold it into a single result with reduce. This approach solves multi-step data-processing tasks in a single stream pipeline.
Exercise Sum nested orders with flatMap + reduce
Create a List<List<Double>> with three inner lists: List.of(12.5, 25.0), List.of(5.0, 8.0), List.of(30.0). Flatten the stream with flatMap(List::stream), then sum with reduce(0.0, Double::sum). Print the result with System.out.println.
Show example solution
import java.util.List;
public class SumAllPrices {
public static void main(String[] args) {
List<List<Double>> orders = List.of(
List.of(12.5, 25.0),
List.of(5.0, 8.0),
List.of(30.0)
);
double total = orders.stream()
.flatMap(List::stream)
.reduce(0.0, Double::sum);
System.out.println(total);
}
}
Test yourself
-
Which collector splits elements into two groups and returns Map<Boolean, List<T>>?
- Collectors.groupingBy
- Collectors.partitioningBy
- Collectors.joining
- Collectors.toList
Show answer
Collectors.partitioningBy — partitioningBy produces two groups from a single condition.
-
Match each collector with its output type
- groupingBy
- Map<K, List<T>>
- partitioningBy
- Map<Boolean, List<T>>
- joining
- String
- reduce(identity, op)
- T
Next lesson: Optional.of