Java 8 習慣用語,第 9 部分 級聯 lambda 表示式
原文地址:https://www.ibm.com/developerworks/cn/java/j-java8idioms9/index.html
Java 8 習慣用語,第 9 部分
級聯 lambda 表示式
可重用的函式有助於讓程式碼變得非常簡短,但是會不會過於簡短呢?
關於本系列Java 8 是自 Java 語言誕生以來進行的一次最重大更新 — 包含了非常豐富的新功能,您可能想知道從何處開始著手瞭解它。在本系列中,作家兼教師 Venkat Subramaniam 提供了一種慣用的 Java 8 程式設計方法:這些簡短的探索會激發您反思您認為理所當然的 Java 約定,同時逐步將新技術和語法整合到您的程式中。
在函數語言程式設計中,函式既可以接收也可以返回其他函式。函式不再像傳統的面向物件程式設計中一樣,只是一個物件的工廠或生成器,它也能夠建立和返回另一個函式。返回函式的函式可以變成級聯 lambda 表示式,特別值得注意的是程式碼非常簡短。儘管此語法初看起來可能非常陌生,但它有自己的用途。本文將幫助您認識級聯 lambda 表示式,理解它們的性質和在程式碼中的用途。
神祕的語法
您是否看到過類似這樣的程式碼段?
x
-> y -> x > y
|
如果您很好奇“這到底是什麼意思?”,那麼您並不孤單。對於不熟悉使用 lambda 表示式程式設計的開發人員,此語法可能看起來像貨物正從快速行駛的卡車上一件件掉下來一樣。
幸運的是,我們不會經常看到它們,但理解如何建立級聯 lambda 表示式和如何在程式碼中理解它們會大大減少您的受挫感。
高階函式
在談論級聯 lambda 表示式之前,有必要首先理解如何建立它們。對此,我們需要回顧一下高階函式(已在本系列第 1 篇文章中介紹)和它們在函式分解中的作用,函式分解是一種將複雜流程分解為更小、更簡單的部分的方式。
首先,考慮區分高階函式與常規函式的規則:
常規函式
- 可以接收物件
- 可以建立物件
- 可以返回物件
高階函式
- 可以接收函式
- 可以建立函式
- 可以返回函式
開發人員將匿名函式或 lambda 表示式傳遞給高階函式,以讓程式碼簡短且富於表達。讓我們看看這些高階函式的兩個示例。
示例 1:一個接收函式的函式
在 Java™ 中,我們使用函式介面來引用 lambda 表示式和方法引用。下面這個函式接收一個物件和一個函式:
public
static int totalSelectedValues(List< Integer >
values,
Predicate< Integer >
selector) {
return
values.stream()
.filter(selector)
.reduce(0,
Integer::sum);
}
|
totalSelectedValues
的第一個引數是集合物件,而第二個引數是 Predicate
函式介面。
因為引數型別是函式介面 (Predicate
),所以我們現在可以將一個 lambda 表示式作為第二個引數傳遞給 totalSelectedValues
。例如,如果我們想僅對一個 numbers
列表中的偶數值求和,可以呼叫 totalSelectedValues
,如下所示:
totalSelectedValues(numbers,
e -> e % 2 == 0);
|
假設我們現在在 Util
類中有一個名為 isEven
的 static
方法。在此情況下,我們可以使用 isEven
作為 totalSelectedValues
的引數,而不傳遞
lambda 表示式:
totalSelectedValues(numbers,
Util::isEven);
|
作為規則,只要一個函式介面顯示為一個函式的引數的型別,您看到的就是一個高階函式。
示例 2:一個返回函式的函式
函式可以接收函式、lambda 表示式或方法引用作為引數。同樣地,函式也可以返回 lambda 表示式或方法引用。在此情況下,返回型別將是函式介面。
讓我們首先看一個建立並返回 Predicate
來驗證給定值是否為奇數的函式:
public
static Predicate< Integer >
createIsOdd() {
Predicate< Integer >
check = (Integer number) -> number % 2 != 0;
return
check;
}
|
為了返回一個函式,我們必須提供一個函式介面作為返回型別。在本例中,我們的函式介面是 Predicate
。儘管上述程式碼在語法上是正確的,但它可以更加簡短。
我們使用型別引用並刪除臨時變數來改進該程式碼:
public
static Predicate< Integer >
createIsOdd() {
return
number -> number % 2 != 0;
}
|
這是使用的 createIsOdd
方法的一個示例:
Predicate< Integer >
isOdd = createIsOdd();
isOdd.test(4);
|
請注意,在 isOdd
上呼叫 test
會返回 false
。我們也可以在 isOdd
上使用更多值來呼叫 tes