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