首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

初探 Lambda 表達式與 Java 多核心程式設計(0):從內部迭代到外部迭代的演進

     編輯:Java 相關知識

系列緣起

假期研讀 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));
}

特點:呼叫端決定「如何」遍歷(順序、條件、步進),集合內部細節暴露給外部。

外部迭代演進

階段 1:forEach 方法(Java 5+)

集合內部封裝遍歷邏輯,呼叫端只需提供「對每個元素做什麼」:

// 重寫 forEach 封裝行為
@Override
public void forEach(Consumer<? super String> action) {
    for (String s : this) {
        action.accept(s);
    }
}

階段 2:行為參數化 - Consumer 介面

@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.");
    }
});

階段 3:Lambda 表達式(Java 8)

編譯器推斷型別,極致簡化:

// 完整寫法
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!

ArrayList 內部 forEach 實作揭秘

@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 迴圈遍歷,但併發檢查與行為分離是關鍵差異。外部迭代為並行流奠定基礎。

核心啟示

  • 內部/外部迭代本質差異在於控制權反轉
  • Lambda 讓「行為參數化」成為一等公民
  • 外部迭代解鎖:並行處理、遲延運算、資料流水線操作
  • 後續章節將展開 Stream API、並行流、Collector 等進階主題
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved