TreeSet底層則采用NavigableMap這個接口來保存TreeSet集合,而實際上NavigableMap只是一個接口,實際上TreeSet還是用TreeMap來保存set元素。
TreeSet初始化的時候會new 一個TreeMap進行初始化;
private transient NavigableMap<E,Object> m;
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
public TreeSet() {
this(new TreeMap<E,Object>());
}
......
TreeMap采用一種被稱為“紅黑樹”的排序二叉樹來保存Map中的的每個Entry——每個Entry都被當做紅黑樹的一個節點來對待;
TreeMap的插入就是一個“排序二叉樹”算法:每當程序添加新節點時,總是從樹的根節點開始比較,即將根節點當成當前節點,如果新增節點大於當前節點且當前節點的右節點存在,則以右節點作為當前節點;如果新增節點小於當前節點且當前節點的左節點存在,則以左節點作為當前節點;如果新增節點等於當前節點,則新增節點覆蓋當前節點;直到某個節點的左右節點不存在,並結束循環;將新增的節點作為該節點的子節點,如果新增的節點大於該節點,則添加成該節點的右節點,如果新增的節點小於該節點,則添加成該節點的左節點;
TreeMap 根據Key來獲取value。
相同點:
(1)都是有序集合,也就是說他們存儲的值(key)都是排好序的。
(2)都是非同步的,因此它們不能在多線程之間共享,不過可以使用方法Collections.synchroinzedMap()或者Collections.synchroinzedSet()來實現同步。
(3)運行速度都要比Hash集合慢,它們內部對元素的操作時間復雜度為O(logN),而HashMap和HashSet則為O(1)。
不同點:
(1)TreeSet和TreeMap實現的接口規范不同,分別實現Set和Map接口。
注意:
TreeSet和TreeMap要求存放的對象(對TreeMap來說是鍵值對映射的鍵)所屬的類必須實現Comparable接口(或者通過Comparator實例化TreeSet和TreeMap對象),該接口提供了比較元素的compareTo()方法,當插入元素時會調用該方法比較元素的大小。
補充:
Collections工具類的sort方法有兩種重載的形式:sort(List<T> list) 與sort(List<T> list, Comparator<? super T> c)
第一種要求傳入的待排序容器中存放的對象所屬的類必須實現Comparable接口以實現元素的比較。
第二種不強制要求待排序容器中存放的對象所屬的類必須實現Comparable接口,但是要求傳入第二個參數,這個參數是Comparator接口的子類型(需要重寫compare方法實現元素的比較),相當於一個臨時定義的排序規則,其實就是通過接口注入比較元素大小的算法,也是對回調模式的應用(Java中對函數式編程的支持)。
---------------------