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