努力努力再努力xLg
[TOC]
函數(shù)式接口的定義
- 函數(shù)式接口就是有且只有一個(gè)抽象方法的接口,都可以稱之為函數(shù)式接口。
- 如
Runnable(),Comparator()都是函數(shù)式接口
- 如
- 加了
@functionalInterface注解。 - 如果沒有添加該注解,但是滿足有且只有一個(gè)抽象方法的接口,都會(huì)被
jdk8認(rèn)為是函數(shù)式接口。 - 在JDK8 之前,java方法之間的調(diào)用都只能傳遞參數(shù),
JDK8之后使用lambda函數(shù)式編程, 實(shí)現(xiàn)了方法之間傳遞行為。
Function接口
import java.util.Objects;
java中所有的方法都是只能返回一個(gè)結(jié)果?。?!
/**
* Represents a function that accepts one argument and produces a result.
* 接受一個(gè)參數(shù)并且產(chǎn)生一個(gè)參數(shù)并且返回
* <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 functionf
* @param <R> the type of the result of the function
*
* @since 1.8
*/
@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);
只接受一個(gè)參數(shù),然后返回一個(gè)參數(shù)
/**
* Returns a composed function that first applies the {@code before}
* function to its input, and then applies this function to the result.
嘗試?yán)斫庖幌逻@句話,返回第一個(gè)適用的函數(shù)作為稍后調(diào)用的方法的輸入,然后調(diào)用這個(gè)方法返回最終結(jié)果。
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of input to the {@code before} function, and to the
* composed function
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before}
* function and then applies this function
* @throws NullPointerException if before is null
*
* @see #andThen(Function)
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
* 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
*
* @see #compose(Function)
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
/**
* 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;
}
}
在上述源碼中,較為難理解的就是compose andThen 兩個(gè)方法了。
其實(shí)這兩個(gè)方法都是為了使用方便而設(shè)計(jì)的,這是JDK8給我們提供的函數(shù)的復(fù)合,這意味著你可以把多個(gè)簡單的Lambda復(fù)合成復(fù)雜的表達(dá)式。
? 上述兩個(gè)方法可以看作JDK為了將Lambda表達(dá)式復(fù)合起來,特意在Function接口中添加的兩個(gè)默認(rèn)方法。他們都會(huì)返回一個(gè)Function實(shí)例。
舉例說明
? 假設(shè)一個(gè)函數(shù)f給數(shù)字做加1操作(x -> x + 1),另一個(gè)函數(shù)g給數(shù)字做乘法操作。使用上述兩個(gè)方法就可以將這兩個(gè)函數(shù)操作復(fù)合起來,是代碼更加簡潔。
compose
Function<Integer,Integer> f = x -> x + 1;
Function<Integer,Integer> g = x -> x * 2;
Function<Integer,Integer> h = f.compose(g);
int result = h.apply(1);
這里得到的答案是3
這是可以看作一個(gè)數(shù)學(xué)的方程解答,使用compose可以看作為數(shù)學(xué)中的f(g(x));
從源碼的JavaDoc中也可以看出,首先調(diào)用該方法返回結(jié)果之前,將該結(jié)果作為參數(shù),計(jì)算出最終結(jié)果
andThen
Function<Integer,Integer> f = x -> x + 1;
Function<Integer,Integer> g = x -> x * 2;
Function<Integer,Integer> h = f.andThen(g);
int result = h.apply(1);
這里得到的答案是4
相當(dāng)于數(shù)學(xué)中的g(f(x))
與compose剛好相反。
andThen有然后的意思,即可以理解,先調(diào)用函數(shù),得到一個(gè)適當(dāng)?shù)膮?shù),然后用該方法本身,最后返回結(jié)果。compose反之。
compose與andThen對比

簡單理解就是一個(gè)調(diào)用的先后順序問題。
研究BiFunction函數(shù)是接口
/**
* Represents a function that accepts two arguments and produces a result.
* This is the two-arity specialization of {@link Function}.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #apply(Object, Object)}.
*
* @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));
}
}
可以看出該函數(shù)式接口的簽名為(T,V)->R:接受兩個(gè)類型參數(shù),返回一個(gè)類型參數(shù),相較于Function()接口多了一個(gè)輸入?yún)?shù)。但是少了一個(gè)Compose方法;為什么呢?
為什么BiFunction沒有Compose方法
假設(shè)如果有的話
default <V> BiFunction<T,U, V> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (T t,U u) -> befor.apply(apply(t,u));
}
// Function 中的compose
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
嘗試?yán)斫?code>BiFunction中的andThen方法
接受的參數(shù)是Function,因?yàn)?code>java在返回結(jié)果中只能返回一個(gè)結(jié)果,使用andThen在計(jì)算完BiFunction中兩個(gè)元素的運(yùn)算之后只能返回一個(gè)結(jié)果并且賦值,如果按照這種邏輯,有compose方法的話,首先計(jì)算的是Function函數(shù),并且只能返回一個(gè)結(jié)果,但是BiFunction中有兩個(gè)參數(shù)需要賦值,所以不能滿足該要求,所以不可能存在compose方法。
Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.andThen(g);
int result = h.apply(1);
System.out.println(result);
BiFunction<Integer, Integer, Integer> ff = (x1, x2) -> x1 + x2 + 1;
BiFunction<Integer, Integer, Integer> hh = ff.andThen(g);
Integer apply = hh.apply(1, 2);
System.out.println(apply);
這里比較難以理解,畫個(gè)重點(diǎn)。
參考書籍
? 《java8實(shí)戰(zhàn)》
本文僅供本人學(xué)習(xí),一起進(jìn)步!