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

Commons Collections 學習筆記(一):Bag 介面設計與 DefaultMapBag 基礎實作

     編輯:Java 相關知識

Commons Collections Bag 介面擴充 Collection,增加元素計數語義。本文解析 Bag/SortedBag 介面契約、基礎實作 DefaultMapBag 核心邏輯、具體實作 HashBag/TreeBag、以及工具類 BagUtils 提供的裝飾器組合式 API。

介面契約

public interface Bag extends Collection {
    int getCount(Object object);           // 取得元素出現次數
    boolean add(Object object);            // 加入單一元素
    boolean add(Object object, int nCopies); // 批量加入
    boolean remove(Object object);         // 移除單一
    boolean remove(Object object, int nCopies); // 批量移除
    Set uniqueSet();                       // 不重複元素集合視圖
    // 繼承: size(), iterator(), containsAll()...
}

public interface SortedBag extends Bag {
    Comparator comparator();
    Object first(); // 最小元素
    Object last();  // 最大元素
}

基礎實作:DefaultMapBag

以 Map<Object, Integer> 為底層存儲,_total 記錄總元素數,_mods 實作快速失效迭代器。

public abstract class DefaultMapBag implements Bag {
    private Map _map; private int _total; private int _mods;

    public boolean add(Object object, int nCopies) {
        _mods++;
        if (nCopies > 0) {
            int count = nCopies + getCount(object);
            _map.put(object, new Integer(count));
            _total += nCopies;
            return (count == nCopies); // true = 新元素
        }
        return false;
    }
    public boolean remove(Object object, int nCopies) {
        _mods++;
        int count = getCount(object);
        if (nCopies <= 0) return false;
        if (count > nCopies) {
            _map.put(object, new Integer(count - nCopies));
            _total -= nCopies; return true;
        } else if (count > 0) {
            _total -= count;
            return (_map.remove(object) != null);
        }
        return false;
    }
    // containsAll/retainAll/equals/hashCode/toString/iterator 完整實作...
    private List extractList() { // 將計數展開為 List
        List result = new ArrayList();
        for (Object o : uniqueSet()) for (int i=getCount(o); i>0; i--) result.add(o);
        return result;
    }
    protected static class BagIterator implements Iterator { ... } // 快速失效
}
  • 計數值用 Integer 包裝,每次修改建立新物件(較 MutableInteger 效能稍遜,但簡單)。
  • extractList() 將 Bag 攤平成 List,供 toArray()/iterator() 使用。
  • uniqueSet() 回傳 UnmodifiableSet.decorate(_map.keySet())。

具體實作

TreeBag 實作 SortedBag,first()/last()/comparator() 委派給 SortedMap。

裝飾器工具類:BagUtils

public class BagUtils {
    public static final Bag EMPTY_BAG = UnmodifiableBag.decorate(new HashBag());
    public static final Bag EMPTY_SORTED_BAG = UnmodifiableSortedBag.decorate(new TreeBag());

    public BagUtils() {} // 應為 private,原碼為 public

    public static Bag synchronizedBag(Bag bag) { return SynchronizedBag.decorate(bag); }
    public static Bag unmodifiableBag(Bag bag) { return UnmodifiableBag.decorate(bag); }
    public static Bag predicatedBag(Bag bag, Predicate p) { return PredicatedBag.decorate(bag, p); }
    public static Bag typedBag(Bag bag, Class type) { return TypedBag.decorate(bag, type); }
    public static Bag transformedBag(Bag bag, Transformer t) { return TransformedBag.decorate(bag, t); }
    // SortedBag 版本對應...
}
  • 提供空 Bag 常數、同步/唯讀/謂詞/型別/轉換等裝飾器工廠方法。
  • TypedBag 內部使用 InstanceofPredicate 實作型別守衛。

版本演進註記

筆記(二)中的 AbstractMapBag 使用 MutableInteger 取代 Integer,解決高頻計數的物件創建開銷,屬後續優化版本。兩版本介面相容,內部實作細節不同。

結語

DefaultMapBag 以 Map 為核心、Integer 為計數器,清晰實現了 Bag 語義,展示了「以組合替代繼承」構建集合框架的經典模式。BagUtils 裝飾器工廠進一步實現功能正交組合。理解此基礎版本,有助於掌握後續 MutableInteger 優化與完整裝飾器體系的設計脈絡。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
類別建構子底層 Map
HashBagHashBag() / HashBag(Collection)new HashMap()
TreeBagTreeBag() / TreeBag(Comparator) / TreeBag(Collection)new TreeMap() / new TreeMap(Comparator)