Java 56: Functional Composition — andThen & compose
easy⏱ 5 mincoursejava
andThen vs compose: the direction
f.andThen(g) produces x -> g(f(x)) — apply f then g (left-to-right reading order). f.compose(g) produces x -> f(g(x)) — apply g first (the classic mathematical f ∘ g). They're mirror images; pick whichever reads naturally. andThen is the more common in pipeline code because it matches the order you write the steps.
Function<Integer,Integer> times2 = x -> x * 2;
Function<Integer,Integer> plus3 = x -> x + 3;
times2.andThen(plus3).apply(5); // (5*2)+3 = 13
times2.compose(plus3).apply(5); // (5+3)*2 = 16
Predicate combinators
Predicate<T> composes with and, or, negate, returning a new predicate. isEven.and(isPositive) short-circuits like &&; isEven.or(isBig) like ||; isEven.negate() flips it. This turns filter conditions into named, testable building blocks instead of one giant boolean lambda — and you can store and reuse each piece.
Compose a transformation pipeline
Implement a composable Fn<A,B> with andThen and compose. Build trim, toUpper, and exclaim and chain trim.andThen(toUpper).andThen(exclaim) over " hello " to get "HELLO!". Then show order matters: times2.andThen(plus3) on 5 = 13, but times2.compose(plus3) on 5 = 16. Also build a Pred<T> with and/or/negate and filter [1..8] by isEven.and(x => x > 3) to get [4,6,8].
Name your functions
Composition pays off most when each step has a name. parseDate.andThen(toUtc).andThen(format) documents intent far better than one inline lambda doing all three. Stored Function/Predicate fields also become unit-testable in isolation — a big maintainability win over giant in-line lambdas.
Quiz: f.compose(g).apply(x)
Given f = x->x*2 and g = x->x+3, what is f.compose(g).apply(5)? 16 — compose runs g first: g(5)=8, then f(8)=16. (andThen would give (5*2)+3 = 13.) Remember: compose = inner-first (mathematical), andThen = left-to-right.