概述
TreeSet是Java集合框架中用於儲存唯一元素的樹形資料結構,它實現了NavigableSet介面,這意味著TreeSet中的元素不僅是有序的,還支援一系列的導航方法。
TreeSet的內部實現主要依賴於TreeMap,透過TreeMap的鍵來維護元素的排序。
類圖
從以上類圖可以看到,TreeSet 實現了三個介面,繼承了一個抽象類:
NavigableSet
介面,提供了強大、靈活的排序與導航功能Serializable
介面,表示TreeSet支援序列化功能Cloneable
介面,表示TreeSet支援克隆AbstractSet
抽象類,主要提供元素對比、刪除等操作
原始碼解讀
成員變數
// 底層依賴TreeMap(TreeMap實現了NavigableMap介面)
private transient NavigableMap<E,Object> m;
// 同HashSet,value使用統一佔位符物件
// value沒有用到為啥不直接用null,因為底層TreeMap插入、移除元素會返回當前元素。如果這裡使用null值,就無法判斷是否插入、移除成功
private static final Object PRESENT = new Object();
構造方法
TreeSet
中提供了四種構造方案:
public TreeSet()
預設建構函式public TreeSet(Comparator<? super E> comparator)
建立一個自定義比較器的TreeSet集合public TreeSet(Collection<? extends E> c)
建立一個包含集合c中所有元素的TreeSet集合public TreeSet(SortedSet<E> s)
建立一個包含SortedSet集合s中所有元素的TreeSet集合,且會複用s的比較器
新增元素
TreeSet的新增元素操作是透過呼叫TreeMap的put方法實現的。
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
與HashSet類似,如果元素不存在於TreeMap中,put方法會返回null,表示新增成功;如果元素已存在,則返回舊值(在這種情況下是PRESENT
),表示新增失敗。
刪除元素
TreeSet的刪除元素操作是透過呼叫TreeMap的remove方法實現的。
public boolean remove(Object o) {
return m.remove(o)==PRESENT;
}
如果成功刪除了元素,remove方法會返回PRESENT
;否則返回null。
獲取元素
TreeSet的獲取元素操作是透過呼叫TreeMap方法實現的,獲取TreeMap key即TreeSet的元素。
// 返回第一個元素
public E first() {
return m.firstKey();
}
// 返回最後一個元素
public E last() {
return m.lastKey();
}
// 返回set中小於e的最大的元素
public E lower(E e) {
return m.lowerKey(e);
}
// 返回set中小於/等於e的最大元素
public E floor(E e) {
return m.floorKey(e);
}
// 返回set中大於/等於e的最大元素
public E ceiling(E e) {
return m.ceilingKey(e);
}
// 返回set中大於e的最小元素
public E higher(E e) {
return m.higherKey(e);
}
遍歷元素
TreeSet的遍歷元素操作是透過呼叫TreeMap方法實現的。升序遍歷(iterator方法)、降序遍歷(descendingIterator方法)。
// 升序遍歷
public Iterator<E> iterator() {
return m.navigableKeySet().iterator();
}
// 降序遍歷
public Iterator<E> descendingIterator() {
return m.descendingKeySet().iterator();
}
出棧元素
TreeSet的出棧元素操作是透過呼叫TreeMap方法實現的。頭結點出棧(pollFirst方法)、尾結點出棧(pollLast方法)。
// 獲取TreeSet中第一個元素,並從Set中刪除該元素
public E pollFirst() {
Map.Entry<E,?> e = m.pollFirstEntry();
return (e == null) ? null : e.getKey();
}
// 獲取TreeSet中最後一個元素,並從Set中刪除該元素
public E pollLast() {
Map.Entry<E,?> e = m.pollLastEntry();
return (e == null) ? null : e.getKey();
}
總結
透過以上的原始碼分析,可以看到TreeSet的底層實現主要依賴於TreeMap。TreeSet利用TreeMap的鍵來儲存元素,並透過TreeMap的排序特性保證了元素的自然排序或自定義排序。