Streams: pipeline thinking, not loop soup
Lazy until someone asks for a result
A Stream is not a data structure — it is a pipeline description. Intermediate operations (map, filter, sorted) build the recipe lazily; only a terminal operation (collect, reduce, forEach, findFirst) actually walks the data. This laziness is what enables short-circuiting and stage fusion.
long activePremium = accounts.stream()
.filter(Account::isActive)
.filter(a -> a.getPlan() == Plan.PREMIUM)
.count();
Map<Region, Long> revenueByRegion = orders.stream()
.collect(Collectors.groupingBy(Order::region,
Collectors.summingLong(Order::cents)));Parallel streams: measure, don't guess
parallelStream() splits the source and fans out work to the common ForkJoinPool. It is great for CPU-bound, stateless transforms on large collections. It is a trap for I/O-bound work, small collections, and anything that touches a shared mutable state. Profile first.
Takeaways
- Streams are lazy recipes; terminals execute them.
- Avoid side effects inside intermediate operations.
- Parallel is a tool, not a decoration.
Enjoying This Lesson?
Your support helps create more comprehensive courses and lessons like this one. Help me build better learning experiences for everyone.
Support Awashyak