Java Function.andThen Method
Last modified: April 16, 2025
The Function.andThen
method is a powerful feature in Java's
functional programming toolkit. It allows chaining multiple functions
together to create complex transformations from simple operations.
This tutorial will explore andThen
in depth with practical
examples. We'll cover basic usage, common patterns, and advanced
composition techniques. Understanding andThen
is essential
for effective functional programming in Java.
Function.andThen Basics
The andThen
method is a default method in the
Function
interface. It returns a composed function that
first applies the current function, then applies the after function.
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after)
The method takes another Function as parameter. The input type of the after function must match or be supertype of current function's output. The result is a new Function that combines both operations.
Simple String Transformation
This example demonstrates basic andThen
usage with string
transformations. We chain uppercase conversion with substring extraction.
package com.zetcode; import java.util.function.Function; public class Main { public static void main(String[] args) { Function<String, String> toUpper = s -> s.toUpperCase(); Function<String, String> firstThree = s -> s.substring(0, 3); Function<String, String> pipeline = toUpper.andThen(firstThree); System.out.println(pipeline.apply("hello")); // Output: HEL System.out.println(pipeline.apply("world")); // Output: WOR } }
The code creates two simple functions and chains them with andThen
.
First string is converted to uppercase, then first three characters are taken.
The pipeline function combines both operations into one transformation.
Mathematical Operations Chaining
This example shows how to chain mathematical operations using
andThen
. We create reusable function components.
package com.zetcode; import java.util.function.Function; public class Main { public static void main(String[] args) { Function<Integer, Integer> square = x -> x * x; Function<Integer, Integer> increment = x -> x + 1; Function<Integer, Integer> half = x -> x / 2; Function<Integer, Integer> pipeline = square.andThen(increment).andThen(half); System.out.println(pipeline.apply(5)); // Output: 13 (5²=25, +1=26, /2=13) System.out.println(pipeline.apply(3)); // Output: 5 (3²=9, +1=10, /2=5) } }
We define three mathematical operations as separate functions. Using
andThen
, we create a pipeline that squares a number,
increments it, then halves the result. Each function is reusable in
other compositions.
Type Transformation Pipeline
This example demonstrates changing types through a function pipeline. We convert String to Integer, then Integer to Double.
package com.zetcode; import java.util.function.Function; public class Main { public static void main(String[] args) { Function<String, Integer> parse = Integer::parseInt; Function<Integer, Double> sqrt = Math::sqrt; Function<String, Double> pipeline = parse.andThen(sqrt); System.out.println(pipeline.apply("16")); // Output: 4.0 System.out.println(pipeline.apply("25")); // Output: 5.0 } }
The pipeline first parses a String to Integer, then calculates square
root producing a Double. andThen
handles the type
transformations automatically. Method references make the code concise.
Combining with Stream.map
This example shows how to use andThen
with Stream.map
for processing collections. We process a list of names.
package com.zetcode; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { Function<String, String> trim = String::trim; Function<String, String> capitalize = s -> s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase(); List<String> names = List.of(" john ", " MARY ", " peter "); List<String> processed = names.stream() .map(trim.andThen(capitalize)) .collect(Collectors.toList()); System.out.println(processed); // Output: [John, Mary, Peter] } }
We create a processing pipeline that first trims strings, then capitalizes them. The composed function is used in Stream.map to process all elements. This pattern is common in data processing applications.
Conditional Processing with andThen
This example demonstrates conditional processing in a function pipeline.
We use andThen
with a function that checks conditions.
package com.zetcode; import java.util.function.Function; public class Main { public static void main(String[] args) { Function<Integer, Integer> doubleVal = x -> x * 2; Function<Integer, String> checkEven = x -> x % 2 == 0 ? "Even: " + x : "Odd: " + x; Function<Integer, String> pipeline = doubleVal.andThen(checkEven); System.out.println(pipeline.apply(3)); // Output: Even: 6 System.out.println(pipeline.apply(4)); // Output: Even: 8 } }
The pipeline first doubles the input number, then checks if it's even.
The second function returns different strings based on the condition.
andThen
enables this sequential processing pattern.
Exception Handling in Pipeline
This example shows how to handle exceptions in function pipelines. We create safe parsing functions that handle NumberFormatException.
package com.zetcode; import java.util.function.Function; public class Main { public static void main(String[] args) { Function<String, Integer> safeParse = s -> { try { return Integer.parseInt(s); } catch (NumberFormatException e) { return 0; } }; Function<Integer, Integer> square = x -> x * x; Function<String, Integer> pipeline = safeParse.andThen(square); System.out.println(pipeline.apply("5")); // Output: 25 System.out.println(pipeline.apply("abc")); // Output: 0 } }
The safeParse function handles potential exceptions by returning a
default value. When chained with square using andThen
,
the pipeline becomes robust against invalid inputs. This is useful
for data validation scenarios.
Complex Object Transformation
This example demonstrates transforming complex objects through a pipeline. We process a Person object through multiple steps.
package com.zetcode; import java.util.function.Function; class Person { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } } public class Main { public static void main(String[] args) { Function<Person, String> getName = p -> p.name; Function<String, String> reverse = s -> new StringBuilder(s).reverse().toString(); Function<String, String> upperCase = String::toUpperCase; Function<Person, String> pipeline = getName.andThen(reverse).andThen(upperCase); Person person = new Person("Alice", 30); System.out.println(pipeline.apply(person)); // Output: ECILA } }
We create a pipeline that extracts a Person's name, reverses it, then
converts to uppercase. Each step is a simple function, but combined
they perform complex transformation. This showcases andThen
's
power for object processing.
Source
Java Function.andThen Documentation
This tutorial covered the Function.andThen
method with
practical examples. Function composition is a powerful technique for
creating reusable, maintainable transformation pipelines in Java.
Author
List all Java tutorials.