Java8 of Function Interface

Java8 added a new feature Function, is a function interface

All marked @FunctionalInterface annotation interface is functional interfaces, specifically, all marked with the annotation interface will be used in the lambda expression.
Look at the source

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
    /**
     * @return a composed function that first applies the {@code before}
     * function and then applies this function
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    /**
     * @return a composed function that first applies this function and then
     * applies the {@code after} function
     */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
    /**
     * Returns a function that always returns its input argument.
     *
     * @param <T> the type of the input and output objects to the function
     * @return a function that always returns its input argument
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

Instantiated
for such interface functions, because only one abstraction function, so long as it is possible to realize the function of the object instance. It is possible to instantiate a "Interface" objects through this line of code following manner:
For example:

Function<Integer, Integer> fun = x -> x + 1;

Wherein the equal sign (=) is the right side of the implement the abstract methods Function interface. In view of this, we can conclude:
a function interface, such as an expression of the form (x -> x + 1) can instantiate an object. And the expression is the realization that the only abstract methods.

Source resolve
1.apply
finished on top of these you can begin to study the source code.
First, we already know Function is a generic class, which defines the two generic parameters T and R, in the Function, T represents the input parameters, the results R represents returned. Maybe you're curious, why not the same with the other java source code, Function of the source code is not specific logic of it?
In fact, this is easy to understand, Function is a function, its role is similar to the definition of a mathematical function,
(the X-, the y-) is almost the same with <T, R> role.

y=f(x)

Function is not so specific operation, the specific operation we need to specify for it, and therefore apply the results of specific returns depends on the incoming lambda expression.

R apply(T t);

for example:

public void test(){
    Function<Integer,Integer> test=i->i+1;
    test.apply(5);
}
/** print:6*/

We define a lambda expression with behavior such that i is incremented by one, we use parameters 5 execution apply, and finally return 6. We used to look at this with the eyes of Java has been different in functional programming before we define a set of operations first thought is to define a method, and then specify the parameters passed in and returns the result we need. Functional programming idea is to not consider specific behavior, but to go to consider parameters specific ways we can follow another set.

Another example:

public void test(){
    Function<Integer,Integer> test1=i->i+1;
    Function<Integer,Integer> test2=i->i*i;
    System.out.println(calculate(test1,5));
    System.out.println(calculate(test2,5));
}
public static Integer calculate(Function<Integer,Integer> test,Integer number){
    return test.apply(number);
}
/** print:6*/
/** print:25*/

We passed through different Function, realized its different operations in the same method. This can greatly reduce the actual development of a lot of duplicate code, for example, I have a new user features in the actual project, but users are divided into VIP and ordinary users, and there are two different new logic. So this time we will be able to write two different logic. In addition, this also allows logic and data separated, we can achieve logic multiplexing.

Of course, the actual development of the logic may be complex, such as two methods F1, F2 requires two logical AB, but need F1 A-> B, F2 method requires B-> A. This we can achieve by just method, source code is as follows:

public void test(){
    Function<Integer,Integer> A=i->i+1;
    Function<Integer,Integer> B=i->i*i;
    System.out.println("F1:"+B.apply(A.apply(5)));
    System.out.println("F2:"+A.apply(B.apply(5)));
}
/** F1:36 */
/** F2:26 */

It is also very simple, but this is not complicated enough, if we F1, F2 require four logical ABCD, then we also have written will become very troublesome.
Understood to be the final R apply (T t) -> function will be applied to the object input parameters, and outputs the result
2.compose and andthen
Compose and andthen solve our problem. Look compose source

default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

Function parameters compose receiving a first logic execution apply incoming, then using the apply current Function return.

default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

andThen now compose the contrary, the first execution of the current logic, then execute the incoming logic.

Say this may not be intuitive, I can give you a look at it another way

B.compose (A) .apply (. 5)
Compose equivalent B.apply (A.apply (. 5)),
B.andThen (A) .apply (. 5))
and is equivalent to andThen A.apply (B. apply (5)).

public void test(){
    Function<Integer,Integer> A=i->i+1;
    Function<Integer,Integer> B=i->i*i;
    System.out.println("F1:"+B.apply(A.apply(5)));
    System.out.println("F1:"+B.compose(A).apply(5));
    System.out.println("F2:"+A.apply(B.apply(5)));
    System.out.println("F2:"+B.andThen(A).apply(5));
}
/** F1:36 */
/** F1:36 */
/** F2:26 */
/** F2:26 */

We can see the return value of the two methods is a Function, so we can use the operating mode of the builder to use.
B.compose (A) .andThen (A) .apply (5);
from the look ahead, look andThen (A) first performing A, i = i + 1 = 6, and then look B.compose (A) first implementation B
I = I the I = 36 and then executed. 1 + I = I A = 37 [
B.andThen (A) .compose (A) .apply (. 5)
from the rear forward, look compose (A) first performing B .compose (A), then B.compose (A) in the first implementation of A
I = I + performed again. 6. 1 = I = I B
I = 36, then perform A i performs Compose (A) = I = 37 [+. 1
. 3 the method identity
Java 8 allows the addition of a specific method in the interface. There are two, default method and the static method, identity () method is a static method Function interface specific interface.
Function.identity () Returns a Lambda expressions like input output target, equivalent to the form t -> t Lambda expressions of the form

static <T> Function<T, T> identity() {
        return t -> t;
    }

Reference:
Exploring Java8 :( ii) the use Function Interface
Function Interface JDK8 of

Published 80 original articles · won praise 140 · views 640 000 +

Guess you like

Origin blog.csdn.net/linjpg/article/details/102544027