Java 8 引入 Lambda 表達式(JSR 335)核心目標是簡化多核並行編程。它不僅帶來函數式編程風格,更配合 default method 解決了集合介面演進的兼容性難題,並催生了強大的 java.util.stream API,實現「外部迭代」與聲明式數據處理。
List<Person> persons = Arrays.asList(
new Person("Joe"), new Person("Jim"), new Person("John")
);
for (Person p : persons) {
p.setLastName("Doe"); // 固定順序、單線程、難以並行
}
persons.forEach(p -> p.setLastName("Doe"));
迭代邏輯交給 JDK 庫,可自動選擇並行、亂序或惰性求值,開發者專注於「做什麼」而非「怎麼做」。
Stream 代表數據流,無數據結構,一次性消費。來源可以是 Collection、陣列、I/O 通道等。操作分兩類:
filter、map)。collect、count、forEach)。// 篩選成年人並轉換為 Adult 對象
List<Adult> adults = persons.stream()
.filter(p -> p.getAge() > 18)
.map(p -> new Adult(p))
.collect(Collectors.toList());
// 統計數量
long count = persons.stream()
.filter(p -> p.getAge() > 18)
.count();
// 指定收集容器類型
List<Adult> adultList = persons.stream()
.filter(p -> p.getAge() > 18)
.map(p -> new Adult(p))
.collect(Collectors.toCollection(ArrayList::new));
每個 Stream 可切換模式:
// 順序
List<Person> seq = list.stream().collect(Collectors.toList());
// 並行
List<Person> par = list.parallelStream().collect(Collectors.toList());
// 或
List<Person> par2 = list.stream().parallel().collect(Collectors.toList());
List original = ...;
List split1 = original.subList(0, mid);
List split2 = original.subList(mid, end);
// 不同線程處理 split1、split2
// 最後合併結果
long t0 = System.nanoTime();
int[] a = IntStream.range(0, 1_000_000).filter(p -> p % 2 == 0).toArray();
long t1 = System.nanoTime();
int[] b = IntStream.range(0, 1_000_000).parallel().filter(p -> p % 2 == 0).toArray();
long t2 = System.nanoTime();
// 輸出示例:serial: 0.06s, parallel: 0.02s
System.out.printf("serial: %.2fs, parallel %.2fs%n", (t1-t0)*1e-9, (t2-t1)*1e-9);
並行流在多核下顯著提升吞吐,但需注意線程安全與任務粒度。
Lambda + Default Method + Stream API 三位一體,讓 Java 集合框架煥然一新。掌握「中間/終端操作」、「順序/並行流」切換,能以極少代碼實現高效、可維護的數據處理管道。