Java 8 發(fā)布帶來的一個(gè)主要特性就是對函數(shù)式編程的支持妓肢。
而 Lambda 表達(dá)式就是一個(gè)新的并且很重要的一個(gè)概念赌结。
它提供了一個(gè)簡單并且很簡潔的編碼方式。
首先從幾個(gè)簡單的 Lambda 表達(dá)式的例子開始了解 Java 中的函數(shù)式編程炬搭。
Lambda 表達(dá)式初識:
首先定義一個(gè) Lambda 表達(dá)式:
x -> x + 1
這個(gè)表達(dá)式輸入?yún)?shù)是一個(gè) x
漏益,然后對這個(gè)參數(shù) x
的操作是加 1,然后將這個(gè)結(jié)果返回粘舟,即返回值熔脂。
從這個(gè)簡單的 Lambda 表達(dá)式可以看出 Lambda 表達(dá)式的語法格式是:
(類型 參數(shù)1, 類型 參數(shù)2) -> { 方法體 }
參數(shù)的小括號可以省略不寫;
方法體的花括號也可以省略不寫(這是因?yàn)榉椒w有兩種類型:單行代碼 或者是 代碼塊柑肴,單行代碼不需要花括號同時(shí) return 關(guān)鍵字省略)霞揉,例如:
(int x, int y) -> { return x + y; }
(int x, int y) -> x + y
x -> x + 1
() -> 3.14
(String s) -> { System.out.println(s); }
第一個(gè)表達(dá)式接收兩個(gè)參數(shù) x 和 y,返回 x + y晰骑;
第二個(gè)表達(dá)式和第一個(gè)表達(dá)式一樣适秩,省略了花括號和 return 關(guān)鍵字;
第三個(gè)表達(dá)式接收一個(gè)參數(shù)硕舆,返回 x+1秽荞;
第四個(gè)表達(dá)式不接收任何參數(shù),返回?cái)?shù)字 3.14岗宣;
第五個(gè)表達(dá)式接收一個(gè)參數(shù)蚂会,沒有返回值。
看到第三個(gè)表達(dá)式耗式,很多新接觸 Lambda 表達(dá)式的朋友不免會有兩個(gè)疑問:x
的類型是什么胁住?這個(gè)整個(gè)函數(shù)的類型是什么呢趁猴,怎么表示它?
接下來就要引入另一個(gè)關(guān)鍵的內(nèi)容彪见,即 java.util.function 包儡司,官方對它的定義是:“Functional interfaces provide target types for lambda expressions and method references. ” 即為定義函數(shù)對象提供的類,也就是如何存儲一個(gè)函數(shù)對象余指。也就是它專門用來解決上面提出的這個(gè)問題:
回到剛剛的這個(gè) Lambda 表達(dá)式:x -> x + 1
捕犬,這個(gè)表達(dá)式接收一個(gè)參數(shù),返回一個(gè)參數(shù)酵镜,我們可以將這個(gè) Lambda 表達(dá)式表示為:
Function<Integer, Integer> add = x -> x + 1;
Function<String, String> concat = x -> x + 1;
第一行代碼里的 x
的類型是 Integer碉碉,它表示將 Integer 類型的參數(shù) x
加 1 然后并返回,即如果參數(shù)是 2淮韭,那么這行代碼返回 3垢粮。
第二行代碼里的 x
的類型是 String,它表示將 String 類型的參數(shù) x
和 "1" 連接并返回靠粪,即如果參數(shù)是 "hi", 那么這行代碼返回 hi1蜡吧。
兩個(gè)參數(shù):
如果我們需要定義兩個(gè)參數(shù)的函數(shù)要怎么寫呢?比如將兩個(gè) Integer 類型的 x
占键,y
進(jìn)行求和并返回結(jié)果昔善?
這里我們需要另一個(gè)類 BiFunction<T, U, R>
,T
表示第一個(gè)輸入?yún)?shù)的類型畔乙,U
表示第二個(gè)輸入?yún)?shù)的類型君仆,R
表示返回值的類型,所以我們的答案是:
BiFunction<Integer, Integer, Integer> sum = (x, y) -> x + y;
只輸入?yún)?shù)不返回結(jié)果:
如果我們需要定義一個(gè)只輸入?yún)?shù)卻不返回結(jié)果的函數(shù)要怎么寫啸澡?這里我們需要另一個(gè)類 Consumer<T>
:
Consumer<String> sayHi = name -> System.out.println("hi, " + name);
如果想要定義輸入兩個(gè)參數(shù)卻不返回結(jié)果的函數(shù)需要用 BiConsumer<T, U>
類袖订,用法和前面提到的 BiFunction
類型一樣氮帐,不再贅述嗅虏。
只返回結(jié)果不輸入?yún)?shù):
如果我們需要定義一個(gè)只返回結(jié)果但不需要輸入?yún)?shù)的函數(shù)要怎么寫?這里我們需要另一個(gè)類 Supplier<T>
:
Supplier<String> getName = () -> "Carl";
如何執(zhí)行函數(shù):
既然有了函數(shù)上沐,那么這些函數(shù)要怎么執(zhí)行呢皮服?
答案是用 apply()
方法:
Integer result = add.apply(2); // 返回 3
String answer = concat.apply("hi"); // 返回 "hi1"
Integer total = sum.apply(1, 2); // 返回 3
String name = getName.apply(); // 返回 "Carl"
結(jié)束語:
之前一直用 C#、Objective-C参咙、Swift 和 Python龄广,因?yàn)榻衲暄芯可A段的課程以 Java 語言為主,所以開始了解一下 Java蕴侧。
感興趣的朋友歡迎關(guān)注本博客择同,也歡迎大家留言討論。
參考資料:
- Beginning Java objects by Jacquie Barker
- Java SE 8: Lambda Quick Start
- The big change in Java SE 8
- Functional Programming with Java 8 Functions