Composition & Judgment
intermediate13 min readLesson 80 of 180
Composing functions and pipelines โ and the honest checklist for when a loop is clearer than a stream.
Functional composition โ and when NOT to stream
Streams compose: map โ filter โ sorted โ collect reads as a
data pipeline. Function types compose too:
Function<String, String> trim = String::trim;
Function<String, String> lower = String::toLowerCase;
Function<String, String> clean = trim.andThen(lower);
But the intermediate skill is judgment:
Stream when: transforming data, grouping, reductions, parallelizable independent work.
Loop when: early exit matters (break beats takeWhile for
readability), you're updating external state, indices are involved, or
the stream version needs three nested collectors to express one idea.
// clear loop
for (int i = 0; i < xs.size(); i++) {
if (xs.get(i).matches(q)) return i; // index + early exit
}
// awkward stream
IntStream.range(0, xs.size()).filter(i -> xs.get(i).matches(q)).findFirst().orElse(-1);
The loop is not a failure of style โ it's the clearer program here.