天天看點

Java8——接口Function

工作中遇到了該接口,檢視源碼寫下自己的了解

jdk源碼如下:

public interface Function<T, R> {

    R apply(T t);

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

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

接口解讀:

1.函數式接口,隻存在一個抽象方法R apply(T t)

2.該接口兩個類型變量T代表入參類型,R代表傳回值類型,該接口主要用于對T類型參數進行處理,傳回R類型的值

andThen方法

假設存在以下僞代碼

public static void main(String[] args) {
	T1 param=...;
	Function<T1,R1> param1=(t)->{fx1(t)}
	Function<T2,R2> param2=(t)->{fx2(t)}
	param1.andThen(param2).apply(param)
}
           

①首先是param1.andThen(param2)

//andThen方法源碼,此處類型參數V由編譯器自動推導得出,傳回類型同樣是個Function接口類型的對象
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t) -> after.apply(apply(t));
}
           

看到apply(t),此處的隐式參數是param1,是以調用的是param1.apply(t),執行

fx1(t),傳入T1類型參數,傳回R1類型傳回值
           

得到的傳回值被作為參數傳入after.apply(fx1(t)),而after對象即param2,是以調用為param2.apply(fx1(t)),執行

fx2(fx1(t)),傳入R1類型參數,被T2類型參數接收(是以此處需要滿足R1 extents T2或R1 implements T2),傳回R2類型傳回值
           

是以

傳回的其實是函數式

fx2(fx1(t))
           

傳回對象類型為Function接口類型,其中的apply方法被重寫為

R2 apply(T1 t){
	fx2(fx1(t))
}
//編譯器會自動推導出傳回值類型為R2,是以該Function接口為Function<T1,R2>,如開頭所說,處理T1類型參數,傳回R2類型傳回值
           

②param1.andThen(param2).apply(param),執行如下

fx2(fx1(param))
           

最後可以得出param1.andThen(param2).apply(param)完成了以下事情

public static void main(String[] args) {
	T1 param=...;
	Function<T1,R1> param1=(t)->{fx1(t)}
	Function<T2,R2> param2=(t)->{fx2(t)}
	param1.andThen(param2).apply(param)
}
           

a)将param參數傳入fx1(param),執行完裡面的代碼後,傳回值(假設為middle)作為新參數傳入fx2

b)執行函數fx2(middle)

compose方法——與andThen方法正好相反

a)将param參數傳入fx2(param),執行完裡面的代碼後,傳回值(假設為middle)作為新參數傳入fx1

b)執行函數fx1(middle)

總結

後續還會遇到類似的函數式接口,他們都是大同小異的,主要是為了接收方法體,該方法體會在之後的程式中執行一次或反複執行多次(有興趣可以去了解一下java8引入的lambda表達式)

函數式接口 參數類型 傳回類型 抽象方法名 描述 其他方法
Runnable void run 作為無參數或傳回值的動作執行
Supplier<T> T get 傳回T類型的值
Consumer<T> T void accept 處理T類型的值 andThen
BiConsumer<T,U> T,U void accept 處理T和U類型的值 andThen
Function<T,R> T R apply 處理T類型的值,傳回R類型的值 compose,andThen,identity
BiFunction<T,U,R> T,U R apply 處理T和U類型的值,傳回R類型的值 andThen
UnaryOperator T T apply 處理T類型的值,傳回T類型的值 compose,andThen,identity
BinaryOperator T,T T apply 處理兩個T類型的值,傳回T類型的值 andThen,maxBy,minBy
Predicate<T> T boolean test 布爾值函數 and,or,negate,isEqual
BiPredicate<T,U> T,U boolean test 兩個入參的布爾值函數 and,or,negate