Java SE 8 (JSR 335) 引入 Lambda 表達式,核心目標:以更簡潔語法實現單方法接口,減少樣板代碼,提升開發效率。基於 JDK 8 Build b94,Eclipse 開發環境。
定義:有且僅有一個抽象方法的接口。可用 @FunctionalInterface 註解標註(編譯器會強制檢查)。
JDK 內置示例:
java.lang.Runnable:void run()java.util.Comparator<T>:int compare(T o1, T o2)java.util.function 包:Function<T,R>、Predicate<T>、Consumer<T>、Supplier<T> 等 40+ 標準函數式接口。
(參數列表) -> { 方法體 }
// 或
(參數列表) -> 表達式
x -> x * 2。return。
// 傳統:創建線程
new Thread(new Runnable() {
public void run() {
System.out.println("Run!");
}
}).start();
// Lambda:極致簡潔
new Thread(() -> System.out.println("Run!")).start();
// 集合排序
Collections.sort(list, new Comparator() {
public int compare(Integer x, Integer y) {
return y - x; // 降序
}
});
// Lambda
Collections.sort(list, (x, y) -> y - x);
| 接口 | 方法 | 用途 | 示例 |
|---|---|---|---|
Function<T,R> | R apply(T t) | 轉換/映射 | list.map(s -> s.length()) |
Predicate<T> | boolean test(T t) | 過濾/判斷 | list.filter(s -> s.startsWith("a")) |
Consumer<T> | void accept(T t) | 消費/副作用 | list.forEach(System.out::println) |
Supplier<T> | T get() | 延遲生成/工廠 | () -> new ArrayList() |
UnaryOperator<T> | T apply(T t) | 同類型轉換 | s -> s.toUpperCase() |
BinaryOperator<T> | T apply(T t1, T t2) | 歸約/聚合 | (a, b) -> a + b |
public class CollectionUtils {
public static List map(List input, Function processor) {
List result = new ArrayList<>();
for (T obj : input) {
result.add(processor.apply(obj));
}
return result;
}
public static void main(String[] args) {
List input = Arrays.asList("apple", "orange", "pear");
List lengths = map(input, s -> s.length());
List uppers = map(input, String::toUpperCase); // 方法引用
}
}
| 類型 | 語法 | 等價 Lambda | 示例 |
|---|---|---|---|
| 靜態方法 | ClassName::staticMethod | (args) -> ClassName.staticMethod(args) | Integer::parseInt |
| 實例方法(特定對象) | instance::method | (args) -> instance.method(args) | System.out::println |
| 實例方法(任意對象) | ClassName::method | (obj, args) -> obj.method(args) | String::toUpperCase |
| 構造器 | ClassName::new | (args) -> new ClassName(args) | ArrayList::new |
Listlist = Arrays.asList("a", "b", "c"); // Lambda list.forEach(s -> System.out.println(s)); // 方法引用:更清晰表達意圖 list.forEach(System.out::println); // 構造器引用:工廠模式 List timestamps = Arrays.asList(0L, 1000L); List dates = CollectionUtils.map(timestamps, Date::new);
接口一旦發布,添加新方法會破壞所有實現類。Java 僅支持類單繼承,無法像 Scala Trait / JS Mixin 那樣混入行為。
public interface CurrencyConverter {
BigDecimal convert(Currency from, Currency to, BigDecimal amount);
// 默認實現:批量轉換複用單筆邏輯
default List convertBatch(Currency from, Currency to, List amounts) {
List result = new ArrayList<>();
for (BigDecimal amt : amounts) {
result.add(convert(from, to, amt));
}
return result;
}
}
default 關鍵字修飾,提供方法體。
interface Loggable {
default void log(String msg) {
System.out.println("[LOG] " + msg);
}
}
interface Serializable {
default String serialize() { ... }
default void deserialize(String data) { ... }
}
class MyService implements Loggable, Serializable {
// 直接擁有 log、serialize、deserialize 行為
}
Collection.removeIf(Predicate):刪除滿足條件元素。Iterable.forEach(Consumer):內部迭代遍歷。Map.computeIfAbsent/putIfAbsent/merge:原子化條件操作。結合 Lambda,集合操作變得極其流暢:
list.removeIf(s -> s.isEmpty()); list.forEach(System.out::println); map.computeIfAbsent(key, k -> expensiveComputation(k));
java.util.function.*)。@FunctionalInterface,防止誤添加第二個抽象方法。list.parallelStream() 適用於 CPU 密集型、無副作用、數據量大的場景。Java SE 8 Lambda 表達式、方法引用、默認方法三大特性協同重塑了 Java 編程範式:
配合 Stream API、CompletableFuture、Optional,Java 正式進入「現代 Java」時代。掌握這三者,是寫出優雅、高效、可維護 Java 代碼的入場券。