Lambda 表達式是 Java SE 8 引入的里程碑特性,標誌著 Java 正式擁抱函數式編程。它不僅大幅精簡程式碼,更為現代多核 CPU 的並行運算提供了原生支援。本文從設計動機、核心概念、語法規則到集合並行處理,系統梳理 Lambda 的完整面貌。
Lambda 本質是一小塊可當作資料傳遞的函數。關鍵在於理解內部迭代:集合自行管理迭代邏輯,開發者只需提供處理每個元素的函數,框架負責並行調度。
// 完整形式:(參數列表) -> { 方法體; return 結果; }
// 單參數可省略括號、單表達式可省略大括號與 return
FileFilter filter = (File f) -> f.isDirectory(); // 目標型別 FileFilter 推導參數型別
FileFilter filter = f -> f.isDirectory(); // 進一步省略
Runnable r = () -> System.out.println("Hello"); // 無參數
Comparator<String> c = (a, b) -> a.length() - b.length(); // 多參數
ActionListener al = e -> { ui.show(); log.info(e); }; // 多語句需大括號,void 回傳型別強制要求
void,Lambda 主體必須用 { ... } 包裹(語法限制)。for (String s : list) {
if (s.contains(keyword)) System.out.println(s);
}
控制流在集合外部,難以並行化,且易產生 ConcurrentModificationException。
list.stream()
.filter(s -> s.contains(keyword))
.forEach(System.out::println);
集合內部管理迭代,可無縫切換 parallelStream() 實現多核並行。
| 模式 | 意圖 | Stream 方法 | Lambda 範例 |
|---|---|---|---|
| Filter(過濾) | 保留符合條件的元素 | filter(Predicate) | s -> s.equalsIgnoreCase(target) |
| Map(映射) | 元素轉換為新形式 | map(Function) | s -> s.toUpperCase() |
| Reduce(化簡) | 聚合為單一結果 | reduce() / collect() | (a, b) -> a + b |
// Java 7 外部迭代 List<String> out = new ArrayList<>(); for (String s : myStrings) if (s.equalsIgnoreCase(possible)) out.add(s); log(out); // Java 8 一行式內部迭代 log(myStrings.stream().filter(s -> s.equalsIgnoreCase(possible)).collect(toList()));
Predicate<T>:boolean test(T t) —— 過濾判斷Function<T,R>:R apply(T t) —— 映射轉換Consumer<T>:void accept(T t) —— 消費處理Supplier<T>:T get() —— 延遲產生BinaryOperator<T>:T apply(T t1, T t2) —— 化簡合併所有介面均為單抽象方法(SAM),完美契合 Lambda。
// 循序處理 long sum = list.stream().mapToLong(Long::longValue).sum(); // 並行處理:僅多一個 parallel() long sum = list.parallelStream().mapToLong(Long::longValue).sum();
框架自動分割資料、分配執行緒池、合併結果,開發者無需手動管理執行緒。
String::length 比 s -> s.length() 更簡潔。Lambda 表達式配合 Stream API,讓 Java 開發者以聲明式風格編寫並行安全、可讀性極高的程式碼。掌握「行為參數化」與「內部迭代」兩大核心思想,是邁向現代 Java 開發的關鍵門檻。