Apache Commons Collections (v4+) 提供豐富的函數式編程組件,讓 Java 集合操作更聲明式、可組合。本文系統講解核心接口與實戰模式。
Predicate 代表 boolean test(T),替代 if-else 鏈。
// 相等判斷 Predicateeq = EqualPredicate.equalPredicate("liguodong"); // 或 new EqualPredicate<>("liguodong") // 非空判斷 Predicate
Predicatelen5to20 = obj -> obj.length() >= 5 && obj.length() <= 20; // Java 8+ Lambda 极简 // 兼容舊版:new Predicate<>() { public boolean evaluate(String o) { ... } }
Listlist = PredicatedList.predicatedList(new ArrayList<>(), allPredicate(notNull, len5to20)); list.add("liguodong"); // ✅ // list.add(null); // ❌ NPE // list.add("byby"); // ❌ IAE (長度不足)
Transformer 代表 O transform(I),配合 CollectionUtils.collect 實現映射。
// Long (時間戳) → String (格式化日期) Transformerts2str = input -> new SimpleDateFormat("yyyy年MM月dd日").format(input); List timestamps = Arrays.asList(99999999L, 30000L); Collection dates = CollectionUtils.collect(timestamps, ts2str);
// 員工 → 等級標籤 PredicatelowSal = 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 代表 void execute(T),配合 CollectionUtils.forAllDo 批量執行。
Closureraise20 = e -> e.setSalary(e.getSalary() * 1.2); CollectionUtils.forAllDo(empList, raise20);
// 打折商品 9 折,否則滿百減 20 Predicatediscounted = 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);
// 確保所有員工薪資 ≥ 10000,每次漲 20% Predicatebelow10k = 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);
// 先打 9 折,再滿百減 20 Closurechain = ChainedClosure.chainedClosure(doDiscount, doSubtract); CollectionUtils.forAllDo(goodsList, chain);
Sets1 = 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
CircularFifoQueueq = new CircularFifoQueue<>(2); // 固定容量 2 q.add("a"); q.add("b"); q.add("c"); q.add("d"); // 只保留 c, d
Queuero = UnmodifiableQueue.unmodifiableQueue(q); // ro.add("x"); // ❌ UnsupportedOperationException
Queuechecked = PredicatedQueue.predicatedQueue(q, NotNullPredicate.INSTANCE); // checked.add(null); // ❌ IllegalArgumentException
| 迭代器 | 功能 | 示例 |
|---|---|---|
| MapIterator | 高效遍歷 Map,避免 keySet 開銷 | IterableMap |
| UniqueFilterIterator | 去重遍歷 | new UniqueFilterIterator<>(list.iterator()) |
| FilterIterator | 自定義過濾 | new FilterIterator(it, obj -> isPalindrome(obj)) |
| LoopingIterator | 循環遍歷 | new LoopingIterator<>(list) 可無限循環 |
| ArrayListIterator | 數組/列表切片遍歷 | new ArrayListIterator<>(arr, 1, 3) 遍歷索引 1~3 |
鍵值雙向唯一,支持 inverseBidiMap() 反轉。
BidiMapmap = new DualHashBidiMap<>(); // 無序 map.put("bj", "bj@test.com"); map.inverseBidiMap().get("bj@test.com"); // → "bj" BidiMap sorted = new DualTreeBidiMap<>(); // 有序(按鍵/值排序)
允許重複元素,統計計數。
Bagbag = 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"; Bagbag = new TreeBag<>(Arrays.asList(text.split(" "))); bag.uniqueSet().forEach(w -> System.out.println(w + "->" + bag.getCount(w)));
<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) 方面仍有獨特價值。