-
一、Lambda 表示式概述
Lambda 表示式是 Java 中引入的一個重要特性,它提供了一種簡潔的方式來表示可傳遞給方法或儲存在變數中的程式碼塊。本質上,它是一種匿名函式,讓開發者可以用更緊湊、更函式式的風格來編寫程式碼,尤其在處理集合操作、事件處理以及與函式式介面配合使用等場景中非常方便。 -
二、Lambda 表示式的語法結構
Lambda 表示式的基本語法格式如下:
(parameters) -> expression 或者 (parameters) -> -
引數部分(parameters):
如果沒有引數,就寫一對空括號 (),例如 () -> System.out.println("無引數的 Lambda")。
若只有一個引數,引數的括號可以省略,像 param -> System.out.println(param)。
當有多個引數時,用逗號隔開,如 (param1, param2) -> param1 + param2。
箭頭(->):這是 Lambda 表示式的標誌性符號,用於分隔引數和表示式或語句塊,表明引數如何對映到執行的程式碼邏輯。 -
表示式或語句塊(expression 或 {statements;}):
如果表示式比較簡單,能直接計算並返回一個值,就直接寫表示式,例如 (a, b) -> a + b,它的返回值就是 a 與 b 相加的結果。
要是邏輯複雜,需要多條語句來實現,那就用大括號括起來形成語句塊,並且如果有返回值,要明確使用 return 語句,像 (int a, int b) -> { int sum = a + b; return sum; }。 -
三、函式式介面與 Lambda 表示式
Lambda 表示式主要用於實現函式式介面。函式式介面是指只包含一個抽象方法的介面(在 Java 8 中可以使用 @FunctionalInterface 註解來顯式標記一個介面是函式式介面,不過即使不標記,只要符合只含一個抽象方法的規則,依然是函式式介面)。
例如,Java 內建的 java.util.function 包中有很多函式式介面:
Runnable 介面,它只有一個抽象方法 void run(),我們可以用 Lambda 表示式來建立 Runnable 的例項,像這樣:
Runnable runnable = () -> System.out.println("使用 Lambda 實現的 Runnable");
Consumer
Consumer<String> consumer = str -> System.out.println("消費的字串是:" + str); consumer.accept("Hello");
Function<T, R> 介面,抽象方法是 R apply(T t),用於接收一個引數並返回一個結果。比如:
Function<Integer, Integer> function = num -> num * 2; int result = function.apply(5); System.out.println(result); // 輸出 10
- 四、Lambda 表示式在集合操作中的應用
在 Java 中,對集合進行遍歷、篩選、對映等操作時,Lambda 表示式結合一些新的方法(如 forEach、filter、map 等)能讓程式碼更加簡潔高效。
以 List 集合為例:
遍歷集合:
List<String> list = Arrays.asList("apple", "banana", "cherry"); list.forEach(str -> System.out.println(str));
這裡使用 forEach 方法結合 Lambda 表示式,很方便地遍歷了列表中的每個元素並列印出來,相比於傳統的 for 迴圈寫法更加簡潔直觀。
篩選元素:
假設我們有一個 List
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6); List<Integer> evenNumbers = numbers.stream() .filter(num -> num % 2 == 0) .collect(Collectors.toList()); System.out.println(evenNumbers);
這裡先透過 stream 方法將集合轉換為流,然後使用 filter 方法配合 Lambda 表示式定義篩選條件(判斷是否為偶數),最後用 collect 方法將符合條件的元素收集起來形成新的列表。
對映元素:
比如想把一個 List
List<String> words = Arrays.asList("hello", "world"); List<String> upperCaseWords = words.stream() .map(str -> str.toUpperCase()) .collect(Collectors.toList()); System.out.println(upperCaseWords);
map 方法結合 Lambda 表示式,按照定義的邏輯(這裡是將字串轉換為大寫)對集合中的每個元素進行轉換,最終得到轉換後的新集合。
-
五、Lambda 表示式的優勢
程式碼簡潔性:極大地減少了樣板程式碼,讓程式碼更加緊湊易讀,尤其是在實現簡單的介面方法邏輯時,避免了像匿名內部類那樣冗長的寫法。
函數語言程式設計風格支援:推動 Java 往函數語言程式設計方向發展,方便進行諸如對集合的函式式操作等,使程式碼邏輯更貼近數學上的函式概念,便於理解和維護。
提高開發效率:編寫程式碼更加迅速,尤其在處理一些回撥邏輯、事件處理器等場景中,能快速定義相應的行為邏輯。 -
六、注意事項
變數作用域:Lambda 表示式中訪問外部變數時,外部變數必須是事實上的 final(即雖然不需要顯式使用 final 關鍵字修飾,但在 Lambda 表示式內部不能對其重新賦值),例如:
int num = 10; Consumer<Integer> consumer = n -> { // num = 20; // 這樣編譯會報錯,不能對外部變數重新賦值 System.out.println(num + n); }; consumer.accept(5);
異常處理:如果 Lambda 表示式中可能丟擲受檢異常(Checked Exception),需要在相應的函式式介面抽象方法宣告中進行異常宣告,或者在 Lambda 表示式內部進行合適的異常處理,不然編譯會報錯。