随着函數式程式設計越來越流行,我們的Java從Java 8開始也引進了函數式程式設計相關的API,再配合lambda表達式的支援,這樣寫起Java代碼會變得越來越爽。Java 8函數相關的api放在java.util.function的包下面,這個包展開後,有一大堆的類,看了有些頭暈,這裡簡單歸類總結一下:

首先可以簡單分為5大類:Consumer、Function、Operator、Predicate和Supplier。
每一類可以指向一種類型的函數。
Consumer:消費者?包含Consumer、IntConsumer、DoubleConsumer、BiConsumer等等。通常用來指向一種接收參數而且沒有傳回值的函數,比如:System.out.println等。下面的代碼是用BiConsumer指向System.out.println并列印:
public static void main(String[] args) {
BiConsumer<PrintStream, Object> op4 = PrintStream::println;
op4.accept(System.out, "haha");
}
Function:包含Function、BiFunction、IntFunction、LongFunction、ToDoubleFunction等等。通常用來指向一種接收參數而且又有傳回值的函數,比如:Math.abs、StringBuilder.append等等。以下代碼就是用BiFunction來指向StringBuilder.append的:
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
BiFunction<StringBuilder, String, StringBuilder> op6 = StringBuilder::append;
op6.apply(sb, "hehe");
System.out.println(sb);
}
Operator:操作符?和Function非常像,差別是Operator要求操作數和傳回值必須是同一類型的,比如Math.abs、String.concat等。包含BinaryOperator、IntBinaryOperator、UnaryOperator、LongUnaryOperator等。下面代碼用IntUnaryOperator指向Math.abs:
public static void main(String[] args) {
IntUnaryOperator op = Math::abs;
System.out.println(op.applyAsInt(-5));
}
Predicate:謂詞?這種類型通常又接收參數,又有傳回值,但傳回值類型必定是boolean。比如:String.startsWith、HashSet.contains等。包含Predicate、DoublePredicate、BiPredicate等。下面代碼用BiPredicate指向String.startsWith:
public static void main(String[] args) {
BiPredicate<String, String> op7 = String::startsWith;
System.out.println(op7.test("seedeed", "see"));
}
Supplier:提供者?這種類型通常沒有參數,但有傳回值,可以應有到一些建立對象的方法,比如工廠方法、單例等。比如ThreadLocalRandom.current、Optional.empty、Collections.emptyList等等。下面代碼用Supplier指向Collections.emptyList:
public static void main(String[] args) {
Supplier<List> op8 = Collections::emptyList;
System.out.println(op8.get().size());
}
說到這裡,貌似沒提到怎麼指向一個沒有參數也沒有傳回值的函數啊。
其實,java.util.function包裡面壓根沒提供這個類。沒關系,我們自己實作一個,非常簡單:
@FunctionalInterface
interface Action {
void action();
}
定義好接口,并用@FunctionalInterface修飾這是一個函數式接口後,下面的代碼用這個Action來分别指向System.gc和自己實作的一個方法——sayHello:
public static void main(String[] args) {
Action op9 = System::gc;
op9.action();
op9 = TestFunction::sayHello;
op9.action();
}
private static void sayHello() {
System.out.println("hello seedeed!");
}
可以看到,成功列印hello seedeed!了!!