上一篇我們用 Predicate 變量重用了固定字母的篩選邏輯。但若需「按任意字母篩選」,每個字母都寫一個 Predicate 依然冗余。本文引入高階函數、詞法作用域與閉包,實現參數化邏輯復用。
Predicate<String> startsWithN = name -> name.startsWith("N");
Predicate<String> startsWithB = name -> name.startsWith("B");
// 更多字母...
邏輯完全相同,僅字母不同,違反 DRY。
public static Predicate<String> checkIfStartsWith(final String letter) {
return name -> name.startsWith(letter); // 閉包:捕獲外部 letter
}
letter 是方法參數,屬於「實際上 final」(effectively final),Lambda 可安全捕獲。Predicate 擁有對 letter 的引用,形成閉包。調用:
friends.stream().filter(checkIfStartsWith("N")).count();
friends.stream().filter(checkIfStartsWith("B")).count();
不想污染類靜態空間,用 Function<String, Predicate<String>> 存在局部變量:
Function<String, Predicate<String>> startsWithLetter =
letter -> name -> name.startsWith(letter); // 柯里化寫法
調用:
friends.stream().filter(startsWithLetter.apply("N")).count();
friends.stream().filter(startsWithLetter.apply("B")).count();
String::length),有捕獲則每次調用工廠方法產生新實例,有微小開銷。int[] counter = {0} 並在 Lambda 中修改 counter[0]++,雖編譯通過,但破壞函數式純粹性,導致併發錯誤。| 特性 | Predicate<T> | Function<T, R> |
|---|---|---|
| 參數 | T | T |
| 返回 | boolean | R |
| 典型用途 | filter、條件判斷 | map、轉換、工廠方法 |
| 組合方法 | and/or/negate | andThen/compose |
高階函數(返回函數的函數)配合閉包,能將「參數化邏輯」封裝為可重用的函數工廠。掌握 Function<T, Predicate<R>> 柯里化模式,是函數式編程消除冗余的核心技巧。下一篇將探討 Comparator 的函數式重構與鏈式比較器。