假期研讀 Oracle 官方著作《Mastering Lambda Expressions: Java Multicore Programming》,內容精簡易懂,適合有 Java 基礎的開發者。本系列將逐章萃取重點、補充實作驗證代碼,歡迎交流指正。
早期集合遍歷由呼叫端顯式控制迭代流程:
// 使用 Iterator 顯式控制
for (Iterator<String> it = contactList.iterator(); it.hasNext(); ) {
System.out.println(it.next());
}
// 或索引迴圈
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
特點:呼叫端決定「如何」遍歷(順序、條件、步進),集合內部細節暴露給外部。
集合內部封裝遍歷邏輯,呼叫端只需提供「對每個元素做什麼」:
// 重寫 forEach 封裝行為
@Override
public void forEach(Consumer<? super String> action) {
for (String s : this) {
action.accept(s);
}
}
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
使用匿名內部類傳遞行為:
contactList.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s + " is your contact.");
}
});
編譯器推斷型別,極致簡化:
// 完整寫法
contactList.forEach((String s) -> { System.out.println(s + " again!"); });
// 型別推斷 + 單一語句省略大括號
contactList.forEach(s -> System.out.println(s + " again!"));
import java.util.ArrayList;
import java.util.Iterator;
import java.util.function.Consumer;
public class ContactList extends ArrayList<String> {
@Override
public void forEach(Consumer<? super String> action) {
super.forEach(action);
}
public static void main(String[] args) {
ContactList contactList = new ContactList();
contactList.add("Foo");
contactList.add("Bar");
contactList.add("Nico");
// 1. 內部迭代
for (Iterator<String> it = contactList.iterator(); it.hasNext(); ) {
System.out.println(it.next());
}
System.out.println("\n--- Consumer 匿名類 ---\n");
contactList.forEach(new Consumer<String>() {
@Override public void accept(String s) {
System.out.println(s + " is your contact.");
}
});
System.out.println("\n--- Lambda 表達式 ---\n");
contactList.forEach(s -> System.out.println(s + " is your contact, again!"));
}
}
Foo
Bar
Nico
--- Consumer 匿名類 ---
Foo is your contact.
Bar is your contact.
Nico is your contact.
--- Lambda 表達式 ---
Foo is your contact, again!
Bar is your contact, again!
Nico is your contact, again!
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
@SuppressWarnings("unchecked") final E[] elementData = (E[]) this.elementData;
final int size = this.size;
for (int i = 0; modCount == expectedModCount && i < size; i++) {
action.accept(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
本質上仍是 for 迴圈遍歷,但併發檢查與行為分離是關鍵差異。外部迭代為並行流奠定基礎。