集合框架——TreeSet實現原理及源碼分析

TreeSet是Set接口的子接口SortedSet的唯一的實現類,TreeSet對其中的元素進行排序。

public class TreeSet<E>
extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, Serializable

可以看到TreeSet繼承了AbstractSet並實現了NavigableSet、Cloneable和Serializable等接口,其中NavigableSet接口是基於TreeMap實現的,他需要依賴元素的自然排序或者傳入一個定製的comparator比較器,這樣才能實現元素之間的比較並對元素進行排序,如果一個類並沒有實現Comparable接口並重寫comparaTo()方法,那麼在添加到TreeSet時會拋出java.langClassCastException。

1、TreeSet和TreeMap的關係

TreeSet是基於TreeMap實現的,而TreeMap是基於紅黑樹的數據結構實現的,也就是自平衡的排序二叉樹,那麼TreeSet也是基於紅黑樹的樹結構實現的,通過TreeSet的構造方法就可以看出,TreeSet就是特殊的TreeMap,而且TreeSet中很多方法都是基於TreeMap中的方法實現的。

TreeSet的構造方法:
    private transient NavigableMap<E,Object> m; //使用一個可序列化的NavigableMap來實現TreeSet
    // 使用一個特定的不可更改的Object來作爲TreeMap的value
    private static final Object PRESENT = new Object();
    //構造器1,直接傳入一個NavigableMap來實現TreeSet
    TreeSet(NavigableMap<E,Object> m) {
        this.m = m;
    }
     //構造器2
     //傳入一個TreeMap來實現TreeSet,根據自然排序來實現元素間的比較和排序,因此插入的元素必須實現Comparabel接口並實現comparaTo()方法
    //並且傳入的元素的compareTo()方法的結果必須是一致的,否則會拋出ClassCastException
    public TreeSet() {
        this(new TreeMap<E,Object>());
    }
    //構造器3
    //傳入一個構造器,使用構造器2,並向TreeMap中傳入比較器Comparator,在添加元素的時候,使用Comparator接口的Compara()方法對元素進行比較
    //和排序
    public TreeSet(Comparator<? super E> comparator) {
        this(new TreeMap<>(comparator));
    }
    //構造器4
    //使用構造器1,並把Collection c中的元素添加到TreeSet中
    public TreeSet(Collection<? extends E> c) {
        this();
        addAll(c);
    }
    //利用構造器3,將排序集的比較器傳入,並將排序集s中的元素添加到TreeSet中
    public TreeSet(SortedSet<E> s) {
        this(s.comparator());
        addAll(s);
    }

從TreeSet的構造函數中可以看出,TreeSet就是value爲不可變的Object對象的TreeMap。

此外,TreeSet中國的很多函數都是基於TreeMap中的函數實現的,例如:

迭代器:

public Iterator<E> iterator() {
        return m.navigableKeySet().iterator();
    }

isEmpty()方法:

public boolean isEmpty() {
        return m.isEmpty();
    }

還有很多方法都是這樣基於TreeMap實現的,具體可以看TreeSet的源碼。


2、元素的排序方式

TreeSet的元素排序的兩種方式:自然排序(Comparable接口)和定製比較器(comparator接口)

自然排序:對於實現了comparable接口的對象,在被添加進TreeSet的時候,TreeSet會把該對象提升爲Comparable類型,並調用comparaTo()方法,根據方法的返回值進行排序。

定製比較器comparator:在創建TreeSet的時候,可以傳入定製的比較器Comparator,如果傳入了Comparator的子類對象,Tadd()方法的內部會自動調用Comparator接口中的compare()方法,調用的對象是compare方法的第一個參數,集合中的對象是compare方法的第二個參數。

*TreeSet構造函數什麼都不傳, 默認按照類中Comparable的順序(沒有就報錯ClassCastException),TreeSet如果傳入Comparator, 就優先按照Comparator的順序比較

comparable和comparator的區別:

Comparable:此接口強行對實現它的每個類的對象進行整體排序。這種排序被稱爲類的自然排序,類的 compareTo 方法被稱爲它的自然比較方法

他們都是用來實現集合中元素的比較、排序的,只是comparable是在集合內部定義的方法實現的排序,而comparator是在集合外部實現的排序。

comparator位於包java.util下,而comparable位於包java.lang下。

發佈了56 篇原創文章 · 獲贊 163 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章