Java集合容器系列09 - TreeSet

1、TreeSet介紹

    TreeMap是底層基於TreeMap的NavigableSet實現,容器的元素存儲在TreeMap鍵值對映射的key中,它使用元素的天然順序或者傳入的比較器Comparator對元素進行排序。它爲基本操做例如add、remove、contain提供了log(n)的時間複雜度保證。注意TreeSet不是線程同步的容器,若是有多個線程同時訪問它,且至少有一個線程修改了容器的結構,那麼他必須在外部進行同步處理。通常都是經過對天然封裝該Set實例的對象進行同步操做來完成,若是沒有這樣的對象,那麼可使用Collections.synChronizedSortedSet包裝TreeSet爲一個線程安全的容器。java

    該TreeSet容器返回的迭代器是快速失敗的(fail-fast),即在生成迭代器以後,若是該容器發生告終構部性修改除了經過迭代iterator.remove方法刪除元素以外,迭代器將會拋出ConcurrentModificationException異常,該異常並不能絕對保證,應該只用於檢測異常。安全

 

2、TreeSet數據結構

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable
{
    /** 內部TreeMap實例 **/
    private transient NavigableMap<E,Object> m;

    //靜態對象充當TreeMap實例中的鍵值對中的value,全部key的value都是該對象
    private static final Object PRESENT = new Object();

}

    TreeSet繼承自AbstractSet,AbstractSet提供了Set的一些基本方法實現,大大減小實現TreeSet的工做量,此外它實現了NavigableSet接口,擴展了倒序、獲取給定目標最接近匹配等功能,實現了Clonable支持克隆、java.io.Serializable支持序列化數據結構

3、TreeSet的源碼分析

1 - 構造函數

/**
     * 構造方法,指定NavigableMap實例
     */
    TreeSet(NavigableMap<E,Object> m) {
        this.m = m;
    }

    /**
     * 無參構造方法,默認建立一個TreeMap實例
     */
    public TreeSet() {
        this(new TreeMap<E,Object>());
    }

    /**
     * 構造方法,建立一個空的TreeMap實例並按照方法指定的比較器對元素進行排序
     */
    public TreeSet(Comparator<? super E> comparator) {
        this(new TreeMap<>(comparator));
    }

    /**
     * 構造方法,建立一個空的TreeSet實例,並將方法指定集合c的全部元素填充到TreeSet實例中
     */
    public TreeSet(Collection<? extends E> c) {
        this();
        addAll(c);
    }

    /**
     * 構造方法,建立一個空的TreeSet實例,比較器取方法參數SortedSet對象的s的內部比較器,
     * 將容器s中的全部元素填充到內部TreeMap實例
     */
    public TreeSet(SortedSet<E> s) {
        this(s.comparator());
        addAll(s);
    }

    經過對TreeSet構造函數的分析,咱們能夠了解到TreeSet的底層與HashSet相似,只不過它的底層存儲結構是一個NavagableMap實例,通常是TreeMap對象,全部TreeSet的操做最終都是反映到底層對TreeMap的操做。函數

2 - 其餘成員方法

/**
     * 返回一個遍歷當前容器元素的迭代器
     */
    public Iterator<E> iterator() {
        return m.navigableKeySet().iterator();
    }

    /**
     * 判斷當前容器是否爲空
     */
    public boolean isEmpty() {
        return m.isEmpty();
    }

    /**
     * 返回當前容器是否包含指定元素
     */
    public boolean contains(Object o) {
        return m.containsKey(o);
    }

    /**
     * 添加元素
     */
    public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }

    /**
     * 刪除元素
     */
    public boolean remove(Object o) {
        return m.remove(o)==PRESENT;
    }

    /**
     * 獲取容器第一個元素
     */
    public E first() {
        return m.firstKey();
    }

    /**
     * 獲取容器最後一個元素
     */
    public E last() {
        return m.lastKey();
    }

    經過對TreeSet成員方法的分析,咱們能夠發現它們的實現徹底依賴於底層的NavigableMap實例(通常狀況下能夠簡單視爲TreeMap實例),容器元素對應的是TreeMap實例鍵值對的Key,若想研讀底層實現能夠直接去研讀TreeMap響應方法的源碼。源碼分析

相關文章
相關標籤/搜索