Java - Lambda 表達式

你好,未來的 Java 巫師們!今天,我們將踏上一段令人興奮的旅程,探索 Lambda 表達式的世界。別擔心你對編程是新手——我會一步步引導你理解這個概念,就像我這些年來對無數學生所做的一樣。所以,來一杯咖啡(或者茶,如果你喜歡的話),我們一起來深入探討吧!

Java - Lambda Expressions

什麼是 Lambda 表達式?

想像你在派對上,想對你的朋友們講一個笑話。如果你不用把整個笑話寫下來然後傳遞紙條,直接大聲說出來是不是更方便?這就是 Java 中 Lambda 表達式的作用——它們提供了一種快速且簡潔的方式來表達單方法接口的實例(功能性接口)。

Lambda 表達式在 Java 8 中被引入,以將函數式編程的一些優點帶入 Java。它們使你的代碼更易於閱讀,更簡潔,並且有時更高效。

Lambda 表達式語法

Lambda 表達式的基本語法如下:

(parameters) -> { body }

這就像一個沒有名字的小型函數。讓我們來分解一下:

  • parameters:這些是輸入參數(如果有的話)
  • ->:這個箭頭符號用於將參數與體分開
  • body:這包含了要執行的代碼

Java Lambda 表達式的特點

  1. 類型推斷:Java 通常可以推斷出參數的類型,所以你不總是需要指定它們。
  2. 單一表達式:如果體中只有一個表達式,你可以省略花括號。
  3. 多個參數:你可以有零個、一個或多個參數。
  4. 返回語句:如果體中有單一表達式,返回語句是可選的。

Java Lambda 表達式示例

讓我們來看看一些示例,了解 Lambda 表達式在實際中是如何工作的。

示例 1:簡單的 Lambda 表達式

// 傳統方式
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello, World!");
}
};

// Lambda 方式
Runnable lambdaRunnable = () -> System.out.println("Hello, Lambda World!");

// 執行兩者
runnable.run();
lambdaRunnable.run();

在這個示例中,我們正在創建一個 Runnable 對象。傳統方式需要我們創建一個匿名內部類,而 Lambda 方式則簡潔得多。兩者在運行時都會打印一條消息。

示例 2:帶參數的 Lambda

interface MathOperation {
int operate(int a, int b);
}

public class LambdaExample {
public static void main(String[] args) {
MathOperation addition = (a, b) -> a + b;
MathOperation subtraction = (a, b) -> a - b;

System.out.println("10 + 5 = " + addition.operate(10, 5));
System.out.println("10 - 5 = " + subtraction.operate(10, 5));
}
}

在這裡,我們定義了一個功能性接口 MathOperation,並使用 Lambda 表達式來實現加法和減法操作。注意代碼變得多麼乾淨和易於閱讀!

Java Lambda 表達式的作用域

Lambda 表達式與內部類有相同的作用域。它們可以從外部範圍捕獲變量,但這些變量必須是有效的最終變量(它們的值在初始化後不會變化)。

public class ScopeExample {
public static void main(String[] args) {
int multiplier = 2;
IntUnaryOperator doubler = (n) -> n * multiplier;
System.out.println(doubler.applyAsInt(4)); // 輸出:8

// 這會引起錯誤:
// multiplier = 3;
}
}

在這個示例中,multiplier 是有效的最終變量,可以被用在 Lambda 表達式中。

在 Lambda 表達式中使用常量

常量可以自由地在 Lambda 表達式中使用。它們是使你的 Lambda 表達式更靈活和可重用的好方法。

public class ConstantExample {
private static final int MAGIC_NUMBER = 42;

public static void main(String[] args) {
IntSupplier magicSupplier = () -> MAGIC_NUMBER;
System.out.println("神奇的數字是: " + magicSupplier.getAsInt());
}
}

在這裡,我們在 Lambda 表達式中使用了一個常量 MAGIC_NUMBER。這是完全沒問題的,並不違反任何作用域規則。

在集合中使用 Lambda 表達式

Lambda 表達式在處理集合時特別出色。它們可以使你的代碼更易於閱讀和理解。讓我們看一些例子:

對列表進行排序

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

// 傳統方式
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return b.compareTo(a);
}
});

// Lambda 方式
names.sort((a, b) -> b.compareTo(a));

System.out.println(names); // 輸出:[David, Charlie, Bob, Alice]

遍歷列表

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 傳統方式
for (Integer number : numbers) {
System.out.println(number);
}

// Lambda 方式
numbers.forEach(number -> System.out.println(number));

// 或者更簡潔
numbers.forEach(System.out::println);

過濾列表

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// 獲取偶數
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());

System.out.println(evenNumbers); // 輸出:[2, 4, 6, 8, 10]

在最後這個示例中,我們使用 Stream API 和 Lambda 表達式從我們的列表中過濾出偶數。filter 方法接受一個 Predicate(一個返回 boolean 的函數),我們使用 Lambda 表達式提供這個 Predicate。

結論

好了,各位!我們已經穿越了 Lambda 表達式的領土,從它們的基本語法到它在集合中的實際應用。記住,Lambda 表達式就像烹飪中的調味料——明智地使用它們,它們可以使你的代碼更加美味(所謂的美味,我指的是可讀性和效率)!

與任何新概念一樣,掌握 Lambda 表達式的關鍵在於練習。所以,去試著在你的代碼中使用 Lambda 表達式吧!並記住,即使你在路上遇到錯誤,這也是成長的機會。就像我總是告訴我的學生,在編程中,錯誤只是偽裝成成長機會的挑戰。

繼續編程,持續學習,最重要的是,享受其中!下次見,這是你的鄰居 Java 老師告別。快樂編程!

Credits: Image by storyset