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

Java 函數式編程實戰:閉包與高階函數在業務邏輯中的應用

     編輯:Java 相關知識

從命令式到函數式的思維轉變

Java 長期被視為純命令式語言——通過語句改變程序狀態。但函數式編程(FP)強調「表達式計算」而非「命令執行」,核心優勢在於模組化:將邏輯拆解為更小、更通用、可組合的單元。本文聚焦兩大 FP 基石——閉包與高階函數,並通過 Apache Commons Functor 庫在 Java 中落地實踐。

核心概念速覽

  • 閉包:攜帶詞法環境的函數對象,可像數據一樣傳遞、存儲、延遲執行
  • 高階函數:接受函數為參數、或返回函數的函數
  • 引用透明:相同輸入必得相同輸出,無副作用,利於推理與優化
  • 遞歸替代迴圈:作為控制流機制

Java 中的「隱性閉包」:匿名內部類

你早已在用閉包了——每個實現 Runnable、Comparator 的匿名類本質都是閉包:

Runnable worker = new Runnable() {
    public void run() { parseData(); }  // 封閉了 parseData 調用
};
executor.execute(worker);  // 高階函數:接收函數對象並執行

Collections.sort(list, comparator) 同理:Comparator 是閉包,sort 是高階函數。

兩種構建閉包的技術路線

1. 表達式特化 —— 實現接口

由庫提供通用接口(如 BinaryPredicate),業務代碼實現之:

// 價格比較器
class PriceComparator implements Comparator {
    public int compare(Object o1, Object o2) {
        return ((SETLItem)o1).getPrice() - ((SETLItem)o2).getPrice();
    }
}

// 組裝:IsGreaterThanOrEqual 是庫提供的 BinaryPredicate 實現
BinaryPredicate bp = new IsGreaterThanOrEqual(new PriceComparator());
bp.test(item1, item2);  // 執行比較

優勢:邏輯封裝為對象,可任意傳遞、重用、組合。

2. 表達式合成 —— 組合基本構建塊

庫提供原子操作(Multiply、Subtract、Constant、Identity 等),通過適配器(RightBoundFunction)與組合器(CompositeUnaryFunction、UnaryCompositeBinaryFunction)拼裝複雜邏輯:

// 計算淨價 = (標價 * (1-折扣率)) * (1+稅率)
UnaryFunction calcDiscountedPrice = new RightBoundFunction(new Multiply(), 1 - discountRate);
UnaryFunction calcTax = new RightBoundFunction(new Multiply(), 1 + taxRate);
CompositeUnaryFunction calcNetPrice = new CompositeUnaryFunction(calcTax, calcDiscountedPrice);
Double netPrice = calcNetPrice.evaluate(item.getPrice());

這正是 Currying(柯里化) 與 函數組合 的 Java 實踐。

實戰:用閉包構建業務規則引擎

需求:類別 A 單價 ≥ 100 或 類別 B 單價 ≥ 200 才可打折。

// 原子謂詞
UnaryFunction getItemCat = obj -> ((SETLItem)obj).getCategory();
UnaryFunction getItemPrice = obj -> new Double(((SETLItem)obj).getPrice());
Constant catA = new Constant("A"), catB = new Constant("B");
Constant usd100 = new Constant(100.0), usd200 = new Constant(200.0);

// 組合:屬於 A 且 價格≥100
BinaryPredicateUnaryPredicate belongsToCatA = 
    new BinaryPredicateUnaryPredicate(new UnaryCompositeBinaryPredicate(new IsEqual(), getItemCat, catA));
BinaryPredicateUnaryPredicate moreThanUSD100 = 
    new BinaryPredicateUnaryPredicate(new UnaryCompositeBinaryPredicate(new IsGreaterThanOrEqual(), getItemPrice, usd100));
UnaryAnd catAAndPrice = new UnaryAnd(belongsToCatA, moreThanUSD100);

// 同理構建 catBAndPrice...

// 最終規則:(A且≥100) 或 (B且≥200)
UnaryPredicate isEligibleForDiscount = new UnaryOr(catAAndPrice, catBAndPrice);

// 使用
if (isEligibleForDiscount.test(item)) { ... }

規則對象清晰可視、動態可組裝、極易單元測試——這就是 FP 帶來的模組化紅利。

內部迭代器:集合操作的新範式

外部迭代器(Iterator)由調用者控制遍歷;內部迭代器由集合內部遍歷,調用者只提供「單元處理邏輯」(閉包):

// 篩選價格≥100 的商品並求和
FilteredIterator fi = new FilteredIterator(items.iterator(), moreThanUSD100);
Summer summer = new Summer();  // 實現 UnaryProcedure,累加價格
Algorithms.foreach(fi, summer);  // 高階函數:內部遍歷並應用閉包
int total = summer.getSum();

優勢:遍歷邏輯可復用、支持鏈式過濾、可並行化、無邊界檢查樣板代碼。

集合代數:以一元謂詞表示集合

用 UnaryPredicate 隱式定義集合,集合運算化為邏輯組合:

public static UnaryPredicate union(UnaryPredicate a, UnaryPredicate b) {
    return new UnaryOr(a, b);           // 並集 = 或
}
public static UnaryPredicate intersection(UnaryPredicate a, UnaryPredicate b) {
    return new UnaryAnd(a, b);          // 交集 = 和
}
public static UnaryPredicate difference(UnaryPredicate a, UnaryPredicate b) {
    return new UnaryAnd(a, new UnaryNot(b)); // 差集 = a 且 非 b
}

無需物化集合元素,即可進行無限大集合的邏輯運算。

結語

閉包與高階函數並非學院派玩具,它們早已潛伏在 Java 標準庫(Runnable、Comparator、Visitor 模式)中。Apache Commons Functor 等庫將其系統化、組件化,讓我們能以聲明式、組合式風格編寫業務規則、集合操作、控制流邏輯。在 Java 8+ 時代,Lambda 與 Stream API 更將這一範式推向主流——但理解其底層原理,依然是寫出優雅、可維護代碼的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved