In Java, what is the difference between Function.andThen and Function.compose? Given f.andThen(g) versus f.compose(g), which function runs first?
answer
- andThen = receiver runs first (reading order)
- compose = argument runs first (math f∘g, right-to-left)
- a.andThen(b) == b.compose(a)
- Lazy: only builds a new Function; runs on .apply
- Types must chain (output feeds next input)
basics
~10 sBoth glue two functions into one. f.andThen(g) runs f first, then feeds its result to g. f.compose(g) runs g first, then feeds its result to f. So andThen reads left-to-right; compose reads right-to-left.
solid answer
~40 sFunction<T,R> has two default combinators that build a new Function without running anything. f.andThen(g) returns a function that applies f, then passes f's output into g: x -> g(f(x)). f.compose(g) is the reverse: it applies g first, then f: x -> f(g(x)). The mnemonic is that andThen executes in reading order (the receiver runs first), while compose mirrors the math notation f∘g where the inner function runs first. Types must line up: in andThen, f's output type must match g's input type; in compose, g's output must match f's input. Both are lazy — calling them only constructs a composed Function; nothing executes until you call .apply on the result. Neither mutates f or g; they are pure factory methods.
go deeper
Knows andThen runs the receiver first and compose runs the argument first, and can predict the output of a simple chain.
Explains the equivalence a.andThen(b) == b.compose(a), the type-chaining requirement, and that composition is lazy (builds a Function, runs on apply).
Discusses readability trade-offs (prefer andThen for execution order), wildcard variance in the signatures, and uses composition to build reusable transformation pipelines instead of nested calls.
Frames composition as a building block for declarative pipelines, weighs it against Stream.map chaining and method extraction for maintainability, and notes purity/no-mutation guarantees that make composed functions safely shareable.
## Background: what a Function is In Java, `java.util.function.Function<T, R>` is a **functional interface** — an interface with exactly one abstract method, here `R apply(T t)`. It represents a transformation: give it a `T`, get back an `R`. Because it has a single abstract method, you can supply it with a lambda (`x -> x + 1`) or a method reference (`String::length`). **Composition** means combining two simple functions into a single new function, so that the output of one becomes the input of the other. `Function` provides two **default methods** (concrete methods that live on the interface itself) to do this: `andThen` and `compose`. ## andThen — run the receiver first ``` default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { return (T t) -> after.apply(this.apply(t)); } ``` `f.andThen(g)` returns a brand-new `Function`. When that new function is later applied to a value `x`, it computes `g(f(x))` — **f runs first**, then its result is handed to g. Read it left-to-right: "apply f, **and then** apply g." Example: `Function<Integer,Integer> times2 = n -> n*2; Function<Integer,Integer> plus3 = n -> n+3;` - `times2.andThen(plus3).apply(5)` = `plus3(times2(5))` = `plus3(10)` = `13`. ## compose — run the argument first ``` default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { return (V v) -> this.apply(before.apply(v)); } ``` `f.compose(g)` also returns a new `Function`, but it computes `f(g(x))` — **g (the argument) runs first**. This mirrors mathematical composition `f ∘ g`, which is read right-to-left. - `times2.compose(plus3).apply(5)` = `times2(plus3(5))` = `times2(8)` = `16`. Notice `13 ≠ 16`: order matters whenever the two functions don't commute. ## The relationship `a.andThen(b)` is exactly the same as `b.compose(a)`. They are two views of the same operation; which you pick is a readability choice. Most people prefer `andThen` because it reads in execution order. ## Type alignment - For `f.andThen(g)`: f's **output** type feeds g's **input** type. If `f: T->R`, then `g: R->V`, result `T->V`. - For `f.compose(g)`: g's **output** type feeds f's **input** type. If `f: T->R`, then `g: V->T`, result `V->R`. The wildcards (`? super R`, `? extends V`) just make the methods flexible about super/subtypes; conceptually the types must chain. ## Laziness and purity Both methods are **lazy builders**: calling `andThen`/`compose` does no computation — it only constructs a new `Function` object. The actual work happens later when you call `.apply(...)` on the composed result. They also never mutate the originals; `f` and `g` are untouched, so you can reuse them in other compositions. ## Why it matters Composition lets you build small, testable, single-purpose functions and assemble pipelines without nesting `g(f(x))` by hand or writing intermediate variables. It's the functional analogue of chaining and is heavily used with the Streams API (`map`, `Collectors`) and in configuration/transformation code.
- Rewrite f.compose(g) using andThen.g.andThen(f) — they are equivalent; both compute f(g(x)).
- If f.andThen(g) and f.compose(g) give the same result for some f and g, what does that tell you?That f and g commute under composition (f(g(x)) == g(f(x)) for the inputs used) — e.g. both are 'add a constant'. It's not generally true.
saying these in an interview costs you the question
- Saying compose runs the receiver first — it runs the ARGUMENT first.
- Claiming the methods execute the functions immediately — they only build a composed Function.
- Thinking andThen and compose give the same result for any pair of functions — order matters unless they commute.
- Believing andThen/compose mutate the original functions.