Java Functional Composition
Jakob Jenkov |
Functional composition is a technique to combine multiple functions into a single function which uses the combined functions internally. You can compose individual functions (typically one or more Java Lambda Expressions) into a single function yourself, but Java also comes with built-in support for functional composition to make the job easier for you. In this Java functional composition tutorial I will explain both how to compose functions from smaller functions yourself, and via Java's built-in features.
Java Functional Composition Example
To get started, let me show you an example of Java functional composition. Here is a single function composed from two other functions:
Predicate<String> startsWithA = (text) -> text.startsWith("A");
Predicate<String> endsWithX = (text) -> text.endsWith("x");
Predicate<String> startsWithAAndEndsWithX =
(text) -> startsWithA.test(text) && endsWithX.test(text);
String input = "A hardworking person must relax";
boolean result = startsWithAAndEndsWithX.test(input);
System.out.println(result);
This functional composition example first creates two Predicate implementations in the form
of two lambda expressions. The first Predicate returns true if the String
you pass to it as parameter starts with an uppercase a (A). The second Predicate
returns true if the String passed to it ends with a lowercase x . Note, that the
Predicate interface contains a single unimplemented
method named test() which returns a boolean. It is this method the lambda expressions implement.
After creating the two basic functions, a third Predicate is composed, which calls the
test() methods of the two first functions. This third function returns true if
both of the basic functions return true, and false otherwise.
Finally, this example calls the composed function and prints out the result. Since the text both starts
with an uppercase a (A) and ends with a lowercase x, the composed function will return
true when called with the String "A hardworking person must relax".
Java Functional Composition Support
The example in the previous section showed you how to compose a new function from two other functions.
Several of the functional interfaces in Java
already has support for functional composition built into them. The functional composition support comes in the
shape of default and static methods in the functional interfaces. For more
on default and static methods in interfaces, see my
Java Interfaces tutorial.
Predicate Composition
The Predicate interface (java.util.function.Predicate) contains a few methods that help
you compose new Predicate instances from other Predicate instances. I will cover some
of these methods in the following sections.
and()
The Predicate and() method is a default method. The and()
method is used to combine two other Predicate functions in the same way I showed in the beginning
of this Java functional composition tutorial. Here is an example of functional composition with the
Predicate and() method:
Predicate<String> startsWithA = (text) -> text.startsWith("A");
Predicate<String> endsWithX = (text) -> text.endsWith("x");
Predicate<String> composed = startsWithA.and(endsWithX);
String input = "A hardworking person must relax";
boolean result = composed.test(input);
System.out.println(result);
This Predicate composition example composes a new Predicate from two other
Predicate instances using the and() method of one of the basic Predicate
instances.
The composed Predicate will return true from it's test()
method if both of the Predicate instances it was composed from also return true.
In other words, if both Predicate one and Predicate two return true.
or()
The Predicate or() method is used to combine a Predicate instance
with another, to compose a third Predicate instance. The composed Predicate will
return true if either of the Predicate instances it is composed from return true,
when their test() methods are called with same input parameter as the composed Predicate.
Here is a Java Predicate or() functional composition example:
Predicate<String> startsWithA = (text) -> text.startsWith("A");
Predicate<String> endsWithX = (text) -> text.endsWith("x");
Predicate<String> composed = startsWithA.or(endsWithX);
String input = "A hardworking person must relax sometimes";
boolean result = composed.test(input);
System.out.println(result);
This Predicate or() functional composition example first creates two basic
Predicate instances. Second, the example creates a third Predicate composed
from the first two, by calling the or() method on the first Predicate
and passing the second Predicate as parameter to the or() method.
The output of running the above example will be true because the first of the two
Predicate instances used in the composed Predicate will return true
when called with the String "A hardworking person must relax sometimes".
Function Composition
The Java Function interface (java.util.function.Function) also contains a few
methods that can be used to compose new Function instances from existing ones. I will cover
some of these methods in the following sections.
compose()
The Java Function compose() method composes a new Function instance from
the Function instance it is called on, and the Function instance passed as parameter
to the compose() method.
The Function returned by compose() will first call the Function passed
as parameter to compose(), and then it will call the Function which compose()
was called on. This is easier to understand with an example, so here is a Java Function compose()
example:
Function<Integer, Integer> multiply = (value) -> value * 2; Function<Integer, Integer> add = (value) -> value + 3; Function<Integer, Integer> addThenMultiply = multiply.compose(add); Integer result1 = addThenMultiply.apply(3); System.out.println(result1);
When called with the value 3, the composed Function will first call the
add Function and then the multiply Function. The resulting calculation will
be (3 + 3) * 2 and the result will be 12.
andThen()
The Java Function andThen() method works opposite of the compose() method.
A Function composed with andThen() will first call the Function
that andThen() was called on, and then it will call the Function passed as parameter
to the andThen() method. Here is a Java Function andThen() example:
Function<Integer, Integer> multiply = (value) -> value * 2; Function<Integer, Integer> add = (value) -> value + 3; Function<Integer, Integer> multiplyThenAdd = multiply.andThen(add); Integer result2 = multiplyThenAdd.apply(3); System.out.println(result2);
This example first creates a multiply Function and an add Function. Then the
andThen() method is called on the multiply Function to compose a new Function,
passing the add Function as parameter to andThen().
Calling the Function composed by andThen() with the value 3 will result in the
following calculation
3 * 2 + 3 and the result will be 9.
Note: As mentioned in the beginning, andThen() works opposite of compose().
Therefore, calling a.andThen(b) is actually the same as calling b.compose(a) .
| Tweet | |
Jakob Jenkov | |











