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

Apache Commons Collections 核心組件深度指南:Predicate、Transformer、Closure、集合操作與擴展迭代器

     編輯:關於C++

概述

Apache Commons Collections (v4+) 提供豐富的函數式編程組件,讓 Java 集合操作更聲明式、可組合。本文系統講解核心接口與實戰模式。

一、Predicate 斷言:封裝條件判斷

Predicate 代表 boolean test(T),替代 if-else 鏈。

內置斷言工廠

// 相等判斷
Predicate eq = EqualPredicate.equalPredicate("liguodong");
// 或 new EqualPredicate<>("liguodong")

// 非空判斷
Predicate notNull = NotNullPredicate.INSTANCE;

// 唯一性判斷(配合 PredicatedList)
Predicate unique = UniquePredicate.uniquePredicate();

// 組合斷言
Predicate all = PredicateUtils.allPredicate(p1, p2, p3);  // AND
Predicate any = PredicateUtils.anyPredicate(p1, p2);      // OR
Predicate one = PredicateUtils.onePredicate(p1, p2);      // XOR
Predicate not = PredicateUtils.negatePredicate(p);        // NOT

自定義斷言

Predicate len5to20 = obj -> obj.length() >= 5 && obj.length() <= 20;
// Java 8+ Lambda 极简
// 兼容舊版:new Predicate<>() { public boolean evaluate(String o) { ... } }

應用:驗證集合元素

List list = PredicatedList.predicatedList(new ArrayList<>(), allPredicate(notNull, len5to20));
list.add("liguodong");  // ✅
// list.add(null);       // ❌ NPE
// list.add("byby");     // ❌ IAE (長度不足)

二、Transformer 類型轉換

Transformer 代表 O transform(I),配合 CollectionUtils.collect 實現映射。

內置類型轉換

// Long (時間戳) → String (格式化日期)
Transformer ts2str = input -> 
    new SimpleDateFormat("yyyy年MM月dd日").format(input);

List timestamps = Arrays.asList(99999999L, 30000L);
Collection dates = CollectionUtils.collect(timestamps, ts2str);

條件轉換:SwitchTransformer

// 員工 → 等級標籤
Predicate lowSal = e -> e.getSalary() <= 10000;
Predicate highSal = e -> e.getSalary() > 10000;

Transformer toLow = e -> new Level(e.getName(), "低薪");
Transformer toHigh = e -> new Level(e.getName(), "高薪");

Transformer switchTrans = new SwitchTransformer<>(
    new Predicate[]{lowSal, highSal},
    new Transformer[]{toLow, toHigh},
    null  // 默認轉換器
);

Collection levels = CollectionUtils.collect(employees, switchTrans);

三、Closure 閉包:封裝業務動作

Closure 代表 void execute(T),配合 CollectionUtils.forAllDo 批量執行。

基本操作

Closure raise20 = e -> e.setSalary(e.getSalary() * 1.2);
CollectionUtils.forAllDo(empList, raise20);

條件執行:IfClosure

// 打折商品 9 折,否則滿百減 20
Predicate discounted = Goods::isDiscount;
Closure doDiscount = g -> g.setPrice(g.getPrice() * 0.9);
Closure doSubtract = g -> { if (g.getPrice() >= 100) g.setPrice(g.getPrice() - 20); };

Closure ifClo = IfClosure.ifClosure(discounted, doDiscount, doSubtract);
CollectionUtils.forAllDo(goodsList, ifClo);

循環執行:WhileClosure

// 確保所有員工薪資 ≥ 10000,每次漲 20%
Predicate below10k = e -> e.getSalary() < 10000;
Closure raise = e -> e.setSalary(e.getSalary() * 1.2);

Closure whileClo = WhileClosure.whileClosure(below10k, raise, false); // false=先判斷
CollectionUtils.forAllDo(empList, whileClo);

鏈式執行:ChainedClosure

// 先打 9 折,再滿百減 20
Closure chain = ChainedClosure.chainedClosure(doDiscount, doSubtract);
CollectionUtils.forAllDo(goodsList, chain);

四、集合運算

Set s1 = new HashSet<>(Arrays.asList(1,2,3));
Set s2 = new HashSet<>(Arrays.asList(2,3,4));

Collection union = CollectionUtils.union(s1, s2);        // 1 2 3 4
Collection inter = CollectionUtils.intersection(s1, s2); // 2 3
Collection diff = CollectionUtils.subtract(s1, s2);      // 1

五、特殊隊列

循環隊列 CircularFifoQueue

CircularFifoQueue q = new CircularFifoQueue<>(2); // 固定容量 2
q.add("a"); q.add("b"); q.add("c"); q.add("d"); // 只保留 c, d

只讀隊列 UnmodifiableQueue

Queue ro = UnmodifiableQueue.unmodifiableQueue(q);
// ro.add("x"); // ❌ UnsupportedOperationException

斷言隊列 PredicatedQueue

Queue checked = PredicatedQueue.predicatedQueue(q, NotNullPredicate.INSTANCE);
// checked.add(null); // ❌ IllegalArgumentException

六、迭代器擴展

迭代器功能示例
MapIterator高效遍歷 Map,避免 keySet 開銷IterableMap m = new HashedMap<>(); MapIterator it = m.mapIterator();
UniqueFilterIterator去重遍歷new UniqueFilterIterator<>(list.iterator())
FilterIterator自定義過濾new FilterIterator(it, obj -> isPalindrome(obj))
LoopingIterator循環遍歷new LoopingIterator<>(list) 可無限循環
ArrayListIterator數組/列表切片遍歷new ArrayListIterator<>(arr, 1, 3) 遍歷索引 1~3

七、雙向 Map (BidiMap)

鍵值雙向唯一,支持 inverseBidiMap() 反轉。

BidiMap map = new DualHashBidiMap<>(); // 無序
map.put("bj", "bj@test.com");
map.inverseBidiMap().get("bj@test.com"); // → "bj"

BidiMap sorted = new DualTreeBidiMap<>(); // 有序(按鍵/值排序)

八、Bag (多重集)

允許重複元素,統計計數。

Bag bag = new TreeBag<>(); // 有序
bag.add("a", 5);  // 添加 5 個 a
bag.remove("a", 2); // 移除 2 個
bag.getCount("a");  // → 3
bag.uniqueSet();    // → 不重複元素集合

詞頻統計實例

String text = "this is a cat and that is a mice where is the food";
Bag bag = new TreeBag<>(Arrays.asList(text.split(" ")));
bag.uniqueSet().forEach(w -> System.out.println(w + "->" + bag.getCount(w)));

Maven 依賴

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</groupId>
    <version>4.4</version>
</dependency>

總結

Commons Collections 將「判斷、轉換、動作」標準化為 Predicate/Transformer/Closure,配合集合工具類實現聲明式數據處理。Java 8+ Stream API 雖覆蓋大部分場景,但 Commons Collections 在可復用組件組合、舊版本兼容、特殊數據結構 (BidiMap, Bag, CircularFifoQueue) 方面仍有獨特價值。

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