Functional Java - Streams
Learn Java Streams with map, filter, reduce, collectors, and practical rules to avoid overusing streams.
#java #functional #streams #collections
Why this step matters
Streams let you express data transformations clearly, especially for filtering, aggregation, and reporting logic. Used well, they reduce boilerplate. Used badly, they hurt readability.
Stream pipeline mental model
A stream pipeline has three parts:
- Source (
List,Set, array, etc.) - Intermediate operations (
filter,map,sorted) - Terminal operation (
collect,forEach,count,reduce)
List<String> names = List.of("alice", "bob", "anna");
List<String> result = names.stream()
.filter(n -> n.startsWith("a"))
.map(String::toUpperCase)
.toList();
System.out.println(result); // [ALICE, ANNA]
map, filter, reduce
filter: keep matching elementsmap: transform each elementreduce: combine elements into one result
int total = List.of(10, 20, 30).stream()
.filter(n -> n >= 20)
.reduce(0, Integer::sum);
System.out.println(total); // 50
Collectors
Collectors are used at the end of a pipeline to shape results.
Map<String, Long> countByRole = List.of("admin", "user", "admin").stream()
.collect(Collectors.groupingBy(r -> r, Collectors.counting()));
System.out.println(countByRole); // {admin=2, user=1}
Useful collectors:
toList()/toSet()groupingBy(...)partitioningBy(...)joining(...)counting(),summingInt(...)
Avoid overusing streams
Streams are not always the best choice. Prefer loops when:
- logic is highly stateful
- multiple side effects are needed
- debugging a long chain is harder than reading a simple loop
Common mistakes
- side effects inside
map/filter - creating very long chains with unclear intent
- using streams in hot loops without measuring impact
- assuming parallel streams always improve performance
Practical rule
Use streams for declarative data transformations. Use loops for complex control flow and mutable workflows.
Takeaway
- Think in pipeline steps: source -> transform -> terminal
- Master
map,filter,reduce,collect - Keep stream code short and readable
- Do not force streams when a loop is clearer