Java 8 辣麼大(lambda)表達式不慌之一—–Function
用java 8 的辣麼大(lambda)表達式的時候肯定用到過Function<T, R>
這個東西,但是在我剛剛用的時候他的寫法讓我很彆扭,很不適應,所以就不得不去打開他的源碼看看他到底兒是個什麼鬼。
看起來這個接口挺簡單的,下面總共也就4個接口倆default、一static。
先看看接口說明:Represents a function that accepts one argument and produces a result.
接收一個參數返回一個結果,就這麼簡單,就像y=f(x)這麼簡單。f(x)=x+1,寫成java代碼就是:
Function<Integer,Integer> myFun = (x)->{
return x+1;
};
再看定義的方法:
第一個方法R apply(T t);
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
這個方法簡單,就是用給的參數去執行這個方法,得到結果(有沒有感覺跟那個invoke有點像的感覺?)。拿上面的舉例子:f(x)=x+1 所以 y=x+1,如果x=1那麼執行一下就是y=1+1。寫成java代碼就是:
// myFun就是上面定義的myFUn
Integer applyResult = myFun.apply(1); // applyResult =2
第二個方法Function<V, R> compose(Function<? super V, ? extends T> before)
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
這個方法的返回值還是一個Function,參數也是一個Function。從方法的註釋,或者方法的實現可以看出來(通常我們看到一個方法,先看註釋,大概就知道方法是做什麼的,怎麼使用,然後再看實現與註釋相佐證)這個方法是先apply參數裏面的Function然後返回一個Function。舉個栗子,就是現在有2個函數:y=f(x),z=f(x),所以如果2個函數y=x+1,z=x*3那麼此處就是y=(x*3)+1。寫成java代碼就是:
Function<Integer,Integer> plus = (x)->{
return x+1;
};
Function<Integer,Integer> multip = (x)->{
return x*3;
};
Integer apply = plus.compose(multip).apply(2); // 此處執行的就是2*3+1=7
// 兩個Funtion的調用反過來一下
Integer overApply = multip.compose(plus).apply(2); // 此處執行的就是(2+1)*3=9
第三個方法Function<T, V> andThen(Function<? super R, ? extends V> after)
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
第三個方法一看實現就知道了跟第二個方法是反過來的,直接看代碼:
Function<Integer,Integer> plus = (x)->{
return x+1;
};
Function<Integer,Integer> multip = (x)->{
return x*3;
};
Integer apply = plus.andThen(multip).apply(2); // 此處執行的就是(2+1)*3=9
// 兩個Funtion的調用反過來一下,跟上面的一樣
Integer overApply = multip.andThen(plus).apply(2); // 此處執行的就是2*3+1=7
看完之後有木有暈?有木有感覺下面這個andThen有點多餘?我感覺有略微有點多餘…
第四個方法static <T> Function<T, T> identity()
/**
* 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;
}
這個方法返回一個Function,這個Function返回他的參數,類似於y=f(x)的 y=x。寫成java代碼就是:
Function<Integer, Integer> identity = Function.identity();
Integer apply = identity.apply(5); // apply=5
這個方法看的我有點萌幣,不知道哪裏用的到,如果有朋友知道這方法在哪裏用,怎麼用,請告知,謝謝了!
上面的方法整半天都是隻能傳一個請求參數,然後返回一個值的,萬一有多個參數呢?找一下同一個包下面的其他類,發現Function有個大兄deipublic interface BiFunction<T, U, R>
這個大兄dei的註釋上說了,他有兩個參數,一個返回值,然後下面只有2個方法,一個是apply
方法,執行Function,另一個是andThen
方法,咦,compose方法怎麼沒了?
先不管了,先來試試他的第一個方法R apply(T t, U u);
BiFunction<Integer,Integer,Integer> plus = (x,y)->{
return x+y;
};
BiFunction<Integer,Integer,Integer> multip = (x,y)->{
return x*y;
};
Integer apply = plus.apply(3, 2); // 3+2=5
Integer apply1 = multip.apply(3, 2); // 3*2=6
再看第二個方法
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));
}
返回的是個BiFunction,但是參數是個Function,這樣的話,可以這麼寫:
BiFunction<Integer, Integer, Integer> multip = (x, y) -> {
return x * y;
};
Function<Integer, Integer> sqr = (x) -> {
return x * x;
};
Integer apply = multip.andThen(sqr).apply(3, 5); //(3*5)*(3*5)= 225
他是這麼執行的,先執行2個參數的就是上面的multip 方法,然後得到一個結果,再將結果當做參數去執行只有一個參數的sqr方法。所以難怪沒有反過來執行的compose方法了,因爲不能同時得到2個返回值,所以只能先執行BiFunction方法了。