How do map, filter and reduce compose in a Java stream pipeline, and what does each stage do?
They are the three classic stages of a data pipeline, and each one has a single job.
filter keeps the elements that match a Predicate and drops the rest. It preserves the element type and the count changes. map transforms each element with a Function and keeps the count the same, unless the function returns a stream — in which case it is flatMap, which flattens one level. reduce folds the whole stream down into a single value using a BinaryOperator, and it is the only one of the three that collapses the stream.
The composition rule is simple: each stage takes a stream and returns a stream, until a terminal operation ends the chain. So filter then map means filter first, then transform the survivors. Reversing them changes the meaning — mapping first might transform every element and then throw away most of the results, which is wasted work.
That ordering rule is where a real performance difference shows up. If the filter is cheap and the map is expensive, filter first. If the map is cheap and the filter is expensive, map first. And because the stream is lazy and can short-circuit, putting a limit after a filter stops the source being read at all once enough elements have passed.
One thing worth saying: reduce and collect are alternatives for producing a result. Reduce folds with a binary operation; collect applies a collector, which can be much more expressive — grouping, joining, summarising. When you want a single value, reduce is the natural choice; when you want a collection or a summary, use collect.