1. 程式人生 > 實用技巧 >java8 函式式介面Function和BiFunction

java8 函式式介面Function和BiFunction

java8提供了函式式介面,也叫匿名函式,是我們可以定義一個方法,實現多種功能(行為傳遞),增強了語義(型別推演:指編譯器可以自動知道某些成員的型別) 可以使我們的程式碼變得更加優雅!!!

Function

Function apply

介面原始碼:

@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}
簡單的說 引數為T 返回R

定義一個數學方法:

public static int math(int a, Function<Integer, Integer> function) {
        int result = function.apply(a);
        return result;
}

呼叫這個方法:

public static void main(String[] args) {
        System.out.println(math(2, value -> value + value));//求和  值為4
        System.out.println(math(2, value -> value * value));//求積  值為4
        System.out.println(math(2, value -> value - 1));//求差  值為1
}

可以看到 只定義了一個數學介面 卻可以實現多種功能 函式式介面傳遞的是行為 !!!

Function compose

介面原始碼:

public interface Function<T, R> {
    default <V> Function<V, R> compose(Function< super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
}
接收一個Function型別的引數 把引數的執行結果給呼叫compose方法的function 以此來實現兩個function組合

定義一個測試方法:

public static int test(int a, Function<Integer, Integer> funA, Function<Integer, Integer> funB) {
        return funA.compose(funB).apply(a);
}

呼叫這個方法:

 public static void main(String[] args) {
        System.out.println(test(2, value -> value - 1,value -> value * 2));//值為3
 }

分析:原始碼中最後一行,先執行括號中的before.apply(v) 把他的執行結果作為引數 傳入 Function<T, R>中 (這裡T是V),最後執行apply(v);

先執行funB.apply(2) 得到4 然後把4作為引數傳給funA 然後執行 funcA.apply(4) 得到3

Function andThen

介面原始碼:

public interface Function<T, R> { 
    default<V><T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
}
接收一個Function型別的引數 先執行function本身的apply方法,執行結果作為引數 傳遞給 Function型別的入參after 然後執行 after的apply方法

定義一個測試介面:

public static int test(int a, Function<Integer, Integer> funA, Function<Integer, Integer> funB) {
        return funA.andThen(funB).apply(a);
}

呼叫這個介面:

public static void main(String[] args) {
        System.out.println(test(2, value -> value - 1,value -> value * 2));//值為 2
}

分析:這個和compose剛好反過來 原始碼最後一行先執行括號中的appluy(t)方法 即本function的apply方法 將執行結果作為引數 在執行after.apply() 方法

先執行 funA的apply方法 2-1得到1 然後把1作為引數 執行funB的apply方法 1*2得到2

Function只能傳遞一個引數 要想傳遞兩個引數怎麼辦呢? BiFunction

BiFunction

BiFunction apply

介面原始碼:

@FunctionalInterface
public interface BiFunction<T, U, R> {

    /**
     * Applies this function to the given arguments.
     *
     * @param t the first function argument
     * @param u the second function argument
     * @return the function result
     */
    R apply(T t, U u);
}
T和U都是入參 R是返回值 適用於連個引數的情況

定義一個測試介面:

public static int test(int a, int b, BiFunction<Integer, Integer, Integer> biFunction) {
        return biFunction.apply(a, b);
}

呼叫這個介面:

public static void main(String[] args) {
        System.out.println(test(3, 4, (a,b) -> (a*b) - 1));//值為11
}

分析:挺簡單的 執行兩個引數運算就可以了 可以拓展為String或者其他

BiFunction andThen

介面原始碼:

@FunctionalInterface
public interface BiFunction<T, U, R> {
    default <V> BiFunction<T, U, V> andThen(Function<?super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t, U u) -> after.apply(apply(t, u));
    }    
}

定義一個測試介面:

public static int test(int a, int b, BiFunction<Integer, Integer, Integer> biFunction, Function<Integer, Integer> function) {
        return biFunction.andThen(function).apply(a, b);
}

呼叫這個介面:

public static void main(String[] args) {
        System.out.println(test(4, 3, (v1, v2) -> v1 + v2, v1 -> v1 * v1));//值為 49
}

分析: 原始碼最後一行 先執行括號中的apply方法 也就是 本BiFunction的apply方法 執行4+3得7 作為引數 傳給Function after 執行after得apply方法 即 7*7得49

因為BiFunction得執行結果返回值就一個值 所以他沒有 compose 甚至 andThen中跟的也不能是BiFunction 而是Function