Skip to main content

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.

Now practice

Functional LabReshape data with groupingBy/partitioningBy/toMap/teeing, and judge composition vs loops.3 challenges ยท ยท ~40 min