Collection容器家族(TreeSet原始碼詳解)
阿新 • • 發佈:2018-12-20
一、在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的封裝類物件。提的的就不在此贅述了。