Java8-5-函數式接口進階與默認方法詳解
上一篇咱們快速的藉助示例演示了stream api的簡單應用,體會到了使用stream api對集合處理的便捷和其與函數式接口密不可分的關係,因此爲了更高效的使用stream api,有必要更熟練的掌握函數式接口。Java8中內置了大量的函數式接口,接下來咱們選擇一些比較經常使用的一塊兒學習下。html
Function接口
在以前的文章中,咱們簡單介紹過Function接口中apply方法的應用,除了apply這個抽象方法,Function接口中還內置了兩個比較經常使用的默認方法(接口中增長的有具體實現的方法,擴展了接口功能,子類默認會繼承該實現),看下Function接口源碼segmentfault
/** * Represents a function that accepts one argument and produces a result. * * <p>This is a <a href="package-summary.html">functional interface</a> * whose functional method is {@link #apply(Object)}. * * @param <T> the type of the input to the function * @param <R> the type of the result of the function * * @since 1.8 */ @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)); } /** * 省略 */ }
Function接口定義中有兩個泛型,按着接口文檔說明第一個泛型是輸入類型,第二泛型是結果類型。
compose方法接收一個Function參數before,該方法說明是返回一個組合的函數,首先會應用before,而後應用當前對象,換句話說就是先執行before對象的apply,再執行當前對象的apply,將兩個執行邏輯串起來。
andThen方法接收一個Function參數after,與compose方法相反,它是先執行當前對象的apply方法,再執行after對象的方法。看一個應用示例api
public class FunctionTest { public static void main(String[] args) { FunctionTest functionTest = new FunctionTest(); System.out.println(functionTest.compute1(5,i -> i * 2,i -> i * i));//50 System.out.println(functionTest.compute2(5,i -> i * 2,i -> i * i));//100 } public int compute1(int i, Function<Integer,Integer> after,Function<Integer,Integer> before){ return after.compose(before).apply(i); } public int compute2(int i, Function<Integer,Integer> before,Function<Integer,Integer> after){ return before.andThen(after).apply(i); } }
定義了compute1和compute2兩個方法,compute1方法第一個參數是要計算的數據,第二個參數是後執行的函數,第一個是先執行的函數,由於輸入輸出都是數字類型,因此泛型都指定爲Integer類型,經過after.compose(before);將兩個函數串聯起來而後執行組合後的Funtion方法apply(i)。當調用compute1(5,i -> i 2,i -> i i)時,先平方再乘以2因此結果是50。而compute2方法對兩個Function的調用正好相反,因此結果是100。數組
BiFunction接口
接下來繼續看下另外一個很經常使用的函數式接口BiFunctionapp
/** * This is the two-arity specialization of {@link Function}. * @param <T> the type of the first argument to the function * @param <U> the type of the second argument to the function * @param <R> the type of the result of the function * * @see Function * @since 1.8 */ @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); /** * Returns a composed function that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of output of the {@code after} function, and of the * composed function * @param after the function to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} function * @throws NullPointerException if after is null */ 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)); } }
實際上就是能夠有兩個參數的Function,一樣前兩個泛型表明着入參的類型,第三個表明結果類型。函數
public class BiFunctionTest { public static void main(String[] args) { BiFunctionTest2 biFunctionTest2 = new BiFunctionTest2(); System.out.println(biFunctionTest2.compute(4,5,(a,b) -> a * b,a -> a * 2)); } public int compute(int a, int b, BiFunction<Integer,Integer,Integer> biFunction, Function<Integer,Integer> function){ return biFunction.andThen(function).apply(a,b); } }
看下compute方法,前兩個參數是待計算數據,第三個是一個BiFunction,由於入參和結果都是數組因此三個泛型都定義爲Integer。最後一個參數是Function。計算邏輯是先執行BiFunction而後將結果傳給Funciton在計算最後返回結果,因此使用了andThen方法。咱們想一下,BiFunction的andThen方法爲何接收的是Function類型的參數而不是BiFunction,答案很簡單,由於BiFunction的apply方法接收兩個參數,可是任何一個方法不可能有兩個返回值,因此也沒辦法放在BiFunction前面執行,這也是爲何BiFunction沒有compose方法的緣由。學習
下一篇ui