1. 程式人生 > >Collection容器家族(TreeSet原始碼詳解)

Collection容器家族(TreeSet原始碼詳解)

一、在Collection集合體系中的位置及概述 

        TreeSet繼承自AbstractSet抽象類,實現了NavigableSet、Serializable、Cloneable、RandomAccess介面。它的特點是儲存元素唯一,無序(輸入和輸出無序)。 TreeSet預設情況下是基於TreeMap實現的,是對TreeMap的封裝。預設情況下和TreeMap一樣,採用元素的內部比較器Comparable的compareTo方法來比較元素的大小。如果不用內部比較器,就需要在外部傳入一個Comparator的實現類來比較。由於TreeMap實現中採用紅黑樹實現,所以add,remove,contains方法的時間複雜度最壞情況下能保證log( n )。

二、成員變數

    // 存放元素的Map,必須是實現了NavigableMap介面的類
    private transient NavigableMap<E,Object> m;

    // Dummy value to associate with an Object in the backing Map
    // 一個虛擬值,用於新增元素到map中時,key為元素的值,value用此虛擬值代替
    private static final Object PRESENT = new Object();

三、構造方法

    // 自定義實現了NavigableMap介面的Map來作為實現
    TreeSet(NavigableMap<E,Object> m) {
        this.m = m;
    }

    // 預設構造方法用TreeMap來實現
    public TreeSet() {
        this(new TreeMap<E,Object>());
    }

    // 以定製排序方式建立一個新的 TreeMap,
    // 根據該 TreeSet 建立一個 TreeSet,
    // 使用該 TreeMap 的 key 來儲存 Set 集合的元素
    public TreeSet(Comparator<? super E> comparator) {
        this(new TreeMap<>(comparator));
    }

    //使用引數集合的元素構造本集合
    public TreeSet(Collection<? extends E> c) {
        // 無參構造器建立一個TreeSet,底層以TreeMap儲存集合元素
        this();
        // 向TreeSet中新增Collection集合c裡的所有元素
        addAll(c);
    }

    public TreeSet(SortedSet<E> s) {
        // 呼叫帶比較器引數的構造器建立衣蛾TreeSet,底層以TreeMap儲存集合元素
        this(s.comparator());
        // 向TreeSet中新增SortedSet集合s裡的所有元素
        addAll(s);
    }

其中涉及到addAll方法

    // 將引數集合中所有元素新增到本集合中
    public  boolean addAll(Collection<? extends E> c) {
        // Use linear-time version if applicable
        // 條件:本集合為空、引數集合有元素、引數集合是SortedSet型別、m是TreeMap型別
        if (m.size()==0 && c.size() > 0 &&
            c instanceof SortedSet &&
            m instanceof TreeMap) {
            SortedSet<? extends E> set = (SortedSet<? extends E>) c;
            TreeMap<E,Object> map = (TreeMap<E, Object>) m;
            Comparator<?> cc = set.comparator();    // 獲取比較器
            Comparator<? super E> mc = map.comparator();    // 獲取比較器
            if (cc==mc || (cc != null && cc.equals(mc))) {  // 如果本集合比較器和引數集合比較器相同
                map.addAllForTreeSet(set, PRESENT); // 使用TreeMap的addAllForTreeSet方法將引數集合所有元素新增到本集合
                return true;
            }
        }
        return super.addAll(c); // 不滿足上訴條件,則呼叫AbstractCollection超類的addAll方法新增
    }

其中涉及到TreeMap的addAllForTreeSet方法,檢視我之前的部落格。

四、常用API

1.新增元素

    // 新增元素
    public boolean add(E e) {
        // 呼叫TreeMap的put方法新增
        return m.put(e, PRESENT)==null;
    }

    // 將引數集合中所有元素新增到本集合中
    public  boolean addAll(Collection<? extends E> c) {
        // Use linear-time version if applicable
        // 條件:本集合為空、引數集合有元素、引數集合是SortedSet型別、m是TreeMap型別
        if (m.size()==0 && c.size() > 0 &&
            c instanceof SortedSet &&
            m instanceof TreeMap) {
            SortedSet<? extends E> set = (SortedSet<? extends E>) c;
            TreeMap<E,Object> map = (TreeMap<E, Object>) m;
            Comparator<?> cc = set.comparator();    // 獲取比較器
            Comparator<? super E> mc = map.comparator();    // 獲取比較器
            if (cc==mc || (cc != null && cc.equals(mc))) {  // 如果本集合比較器和引數集合比較器相同
                map.addAllForTreeSet(set, PRESENT); // 使用TreeMap的addAllForTreeSet方法將引數集合所有元素新增到本集合
                return true;
            }
        }
        return super.addAll(c); // 不滿足上訴條件,則呼叫AbstractCollection超類的addAll方法新增
    }

2.刪除元素

    // 清空集合所有元素
    public void clear() {
        // 呼叫TreeMap方法清除
        m.clear();
    }

    // 移除引數元素
    public boolean remove(Object o) {
        // 呼叫TreeMap方法清除
        return m.remove(o)==PRESENT;
    }

3.遍歷操作

    public Iterator<E> iterator() {
        // 呼叫TreeMap方法清除
        return m.navigableKeySet().iterator();
    }

五、總結

        TreeSet原碼中方法比較少,原因是因為他是TreeMap的封裝類物件。提的的就不在此贅述了。