天天看點

Java 8函數式程式設計學習筆記

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

Java 8函數式程式設計學習筆記

首先可以簡單分為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 8函數式程式設計學習筆記

其實,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!了!!

Java 8函數式程式設計學習筆記