Java Functional Programming : 6. Function
This is the multi part series on Java Functional Programming
6. Function
Apart from
the apply
method (which is abstract) the Function functional interface also
has a static method and two default methods. We have seen the
usage of apply method. It converts (or applies) one type to another. Let
us investigate the default and static methods of this functional
interface.
Category
|
Function
|
Interface Definition
|
Function<T, R>
|
Abstract Method
|
R apply (T t)
|
Static Method
|
<T> Function<T,T> identity()
|
Default Method 1
|
<V> Function<T,V> andThen(Function<? super R,?
extends V> after)
|
Default Method 2
|
<V> Function<V,R> compose(Function<? super V,?
extends T> before)
|
Let us see how these methods look from the inside. The static
function identity gives back the lambda function which always returns
its input argument. The method andThen applies the apply
lambda expression and then the result is applied to the expression passed as
the input parameter. The method compose is the reverse operation of andThen.
In this method first apply is applied to the expression passed
as the input parameter and then the result is applied to this expression
represented by the functional interface. Phew !! the statements are quite a mouthful.
static
<T> Function<T, T> identity() {
return t -> t;
}
default
<V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
default
<V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
|
Let us first
investigate the two default functions. This is how you’d use it in your
program.
Function<Integer,
Integer> doubleIt = (c) -> 2 * c;
Function<Integer,
Integer> squareIt = (c) -> c * c;
int doubleAndThenSquareAT = doubleIt.andThen(squareIt).apply(5); //andThen
int firstSquareThenDoubleAT = squareIt.andThen(doubleIt).apply(5);//andThen
// this
does the same thing as above but uses compose instead of andThen
// using
compose means we do not have to reorder and the
// compose
part is evaluated first
int firstSquareThenDoubleC = doubleIt.compose(squareIt).apply(5); //compose
System.out.println("doubleAndThenSquareAT,
5 = " + doubleAndThenSquareAT); //100
System.out.println("firstSquareThenDoubleAT,
5 = " + firstSquareThenDoubleAT); //50
System.out.println("firstSquareThenDoubleC, 5 = " + firstSquareThenDoubleC); //50
|
One function doubles the integer and the other squares it. We can mix
and match the two functions. First we doubled and the squared the integer. In
the next line we reordered the process to squaring first and then doubling. In
the third calculation we kept the order the same as first but used the compose
method instead. The expression within the ‘compose’ is evaluated first.
You would have noticed a static method called identity() in the class Function. What is the use of having a method that returns a reference to itself? Usually you would use them for applying a function to a stream. (We’ll come to the stream later and you can refer this topic back). When you use the method identity() instead of a lambda you avoid creating a new lambda instance every time. Thus, in the first glance you’d see that there is not much difference between these two lines of code. Both of them would print the output : 123456789
List<Integer> iList = Arrays.asList(1,2,3,4,5,6,7,8,9); iList.stream().map(x -> x).forEach(System.out::print); iList.stream().map(Function.identity()).forEach(System.out::print); |
But if you run the code below
you’d notice that no new instance is created identity() whereas
you’ll have a new instance for x
-> x.
Function<Integer, Integer> id1 = Function.identity(); Function<Integer, Integer> id2 = Function.identity(); Function<Integer, Integer> ld1 = x -> x; Function<Integer, Integer> ld2 = x -> x; System.out.println(id1); System.out.println(id2); System.out.println(ld1); System.out.println(ld2); |
When you run the code, you get
the output printed as:
java.util.function.Function$$Lambda$7/250421012@776ec8df
in.java8.funcintf.FunctionExample$$Lambda$9/1283928880@4eec7777
in.java8.funcintf.FunctionExample$$Lambda$10/295530567@3b07d329
<< Prev (Predicate) | Next (TBD) >>
Comments
Post a Comment