1 public class TreeSet<E> extends AbstractSet<E> 2 implements NavigableSet<E>, Cloneable, java.io.Serializable
1 public interface NavigableSet<E> extends SortedSet<E> { 2 E lower(E e); 3 E floor(E e); 4 E ceiling(E e); 5 E higher(E e); 6 E pollFirst(); 7 E pollLast(); 8 Iterator<E> iterator(); 9 NavigableSet<E> descendingSet(); 10 Iterator<E> descendingIterator(); 11 NavigableSet<E> subSet(E fromElement, boolean fromInclusive, 12 E toElement, boolean toInclusive); 13 NavigableSet<E> headSet(E toElement, boolean inclusive); 14 NavigableSet<E> tailSet(E fromElement, boolean inclusive); 15 SortedSet<E> subSet(E fromElement, E toElement); 16 SortedSet<E> headSet(E toElement); 17 SortedSet<E> tailSet(E fromElement); 18 }
1 // 底層使用NavigableMap來保存TreeSet的元素 2 private transient NavigableMap<E,Object> m; 3 4 // Dummy value to associate with an Object in the backing Map 5 // 因爲Set只使用到了Map的key,因此此處定義一個靜態的常量Object類,來充當Map的value 6 private static final Object PRESENT = new Object();
我想,對於PRESENT這個常量不用多解釋了吧,在HashSet中解釋過的。至於這裏的NavigableMap是什麼東西,下面說。html
1 /** 2 * 使用指定的navigable map來構造TreeSet 3 */ 4 TreeSet(NavigableMap<E,Object> m) { 5 this.m = m; 6 } 7 8 /** 9 * 默認構造方法,底層使用TreeMap來存儲TreeSet元素 10 */ 11 public TreeSet() { 12 this(new TreeMap<E,Object>()); 13 } 14 15 /** 16 * 使用指定的構造器,構造一個TreeMap來保存TreeSet的數據 17 */ 18 public TreeSet(Comparator<? super E> comparator) { 19 this(new TreeMap<E,Object>(comparator)); 20 } 21 22 /** 23 * 構造一個指定Collection參數的TreeSet 24 */ 25 public TreeSet(Collection<? extends E> c) { 26 this(); 27 addAll(c); 28 } 29 30 /** 31 * 構造一個指定SortedMap的TreeSet,根據SortedMap的比較器來來維持TreeSet的順序 32 */ 33 public TreeSet(SortedSet<E> s) { 34 this(s.comparator()); 35 addAll(s); 36 }
1 public interface NavigableMap<K,V> extends SortedMap<K,V> { 2 // 獲取小於指定key的第一個節點對象 3 Map.Entry<K,V> lowerEntry(K key); 4 5 // 獲取小於指定key的第一個key 6 K lowerKey(K key); 7 8 // 獲取小於或等於指定key的第一個節點對象 9 Map.Entry<K,V> floorEntry(K key); 10 11 // 獲取小於或等於指定key的第一個key 12 K floorKey(K key); 13 14 // 獲取大於或等於指定key的第一個節點對象 15 Map.Entry<K,V> ceilingEntry(K key); 16 17 // 獲取大於或等於指定key的第一個key 18 K ceilingKey(K key); 19 20 // 獲取大於指定key的第一個節點對象 21 Map.Entry<K,V> higherEntry(K key); 22 23 // 獲取大於指定key的第一個key 24 K higherKey(K key); 25 26 // 獲取Map的第一個(最小的)節點對象 27 Map.Entry<K,V> firstEntry(); 28 29 // 獲取Map的最後一個(最大的)節點對象 30 Map.Entry<K,V> lastEntry(); 31 32 // 獲取Map的第一個節點對象,並從Map中移除改節點 33 Map.Entry<K,V> pollFirstEntry(); 34 35 // 獲取Map的最後一個節點對象,並從Map中移除改節點 36 Map.Entry<K,V> pollLastEntry(); 37 38 // 返回當前Map的逆序Map集合 39 NavigableMap<K,V> descendingMap(); 40 41 // 返回當前Map中包含的全部key的Set集合 42 NavigableSet<K> navigableKeySet(); 43 44 // 返回當前map的逆序Set集合,Set由key組成 45 NavigableSet<K> descendingKeySet(); 46 47 // 返回當前map中介於fromKey(fromInclusive是否包含)和toKey(toInclusive是否包含) 之間的子map 48 NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, 49 K toKey, boolean toInclusive); 50 51 // 返回介於map第一個元素到toKey(inInclusive是否包含)之間的子map 52 NavigableMap<K,V> headMap(K toKey, boolean inclusive); 53 54 // 返回當前map中介於fromKey(inInclusive是否包含) 到map最後一個元素之間的子map 55 NavigableMap<K,V> tailMap(K fromKey, boolean inclusive); 56 57 // 返回當前map中介於fromKey(包含)和toKey(不包含)之間的子map 58 SortedMap<K,V> subMap(K fromKey, K toKey); 59 60 // 返回介於map第一個元素到toKey(不包含)之間的子map 61 SortedMap<K,V> headMap(K toKey); 62 63 // 返回當前map中介於fromKey(包含) 到map最後一個元素之間的子map 64 SortedMap<K,V> tailMap(K fromKey); 65 }
1 /** 2 * 利用NavigableMap的put方法實現add方法 3 */ 4 public boolean add(E e) { 5 return m .put(e, PRESENT)== null; 6 } 7 8 /** 9 * 利用NavigableMap的remove方法實現add方法 10 */ 11 public boolean remove(Object o) { 12 return m .remove(o)==PRESENT; 13 } 14 15 /** 16 * 添加一個集合到TreeSet中 17 */ 18 public boolean addAll(Collection<? extends E> c) { 19 // Use linear-time version if applicable 20 // 若是集合c是SortedSet的子類,而且m是TreeMap的子類,則用下面的方法添加(主要爲了檢查是否須要從新排序) 21 if (m .size()==0 && c.size() > 0 && 22 c instanceof SortedSet && 23 m instanceof TreeMap) { 24 SortedSet<? extends E> set = (SortedSet<? extends E>) c; 25 TreeMap<E,Object> map = (TreeMap<E, Object>) m; 26 // 取出集合c的比較器 27 Comparator<? super E> cc = (Comparator<? super E>) set.comparator(); 28 // 取出當前set的比較器 29 Comparator<? super E> mc = map.comparator(); 30 // 若是上面的兩種比較器是同一個的話(==或equals),固然TreeSet和TreeMap默認構造方法比較器都是null,這裏也是==的 31 if (cc==mc || (cc != null && cc.equals(mc))) { 32 // 將集合c在當前set集合順序的基礎上,按順序插入 33 map.addAllForTreeSet(set, PRESENT); 34 return true; 35 } 36 } 37 38 // 不須要排序的話就按普通方法,調用父類AbstractCollection的addAll方法(將集合c添加到Set尾部) 39 return super.addAll(c); 40 } 41 42 43 /** 44 * 添加一個集合到TreeSet中 45 */ 46 public boolean removeAll(Collection<?> c) { 47 boolean modified = false; 48 49 // 判斷當前TreeSet元素個數和指定集合c的元素個數,目的是減小遍歷次數 50 if (size() > c.size()) { 51 // 若是當前TreeSet元素多,則遍歷集合c,將集合c中的元素一個個刪除 52 for (Iterator<?> i = c.iterator(); i.hasNext(); ) 53 modified |= remove(i.next()); 54 } else { 55 // 若是集合c元素多,則遍歷當前TreeSet,將集合c中包含的元素一個個刪除 56 for (Iterator<?> i = iterator(); i.hasNext(); ) { 57 if (c.contains(i.next())) { 58 i.remove(); 59 modified = true; 60 } 61 } 62 } 63 return modified; 64 }
4.是否包含java
1 /** 2 * 利用TreeMap的containsKey方法實現contains方法 3 */ 4 public boolean contains(Object o) { 5 return m .containsKey(o); 6 } 7 8 /** 9 * 檢查是否包含指定集合中全部元素,該方法在AbstractCollection中 10 */ 11 public boolean containsAll(Collection<?> c) { 12 // 取得集合c的迭代器Iterator 13 Iterator<?> e = c.iterator(); 14 // 遍歷迭代器,只要集合c中有一個元素不屬於當前HashSet,則返回false 15 while (e.hasNext()) 16 if (!contains(e.next())) 17 return false; 18 return true; 19 }
5.容量檢查設計模式
1 /** 2 * Returns the number of elements in this set (its cardinality). 3 * 4 * @return the number of elements in this set (its cardinality) 5 */ 6 public int size() { 7 return map .size(); 8 } 9 10 /** 11 * Returns <tt>true</tt> if this set contains no elements. 12 * 13 * @return <tt> true</tt> if this set contains no elements 14 */ 15 public boolean isEmpty() { 16 return map .isEmpty(); 17 }
1 public E pollFirst() { 2 Map.Entry<E,?> e = m.pollFirstEntry(); 3 return (e == null)? null : e.getKey(); 4 } 5 6 public E pollLast() { 7 Map.Entry<E,?> e = m.pollLastEntry(); 8 return (e == null)? null : e.getKey(); 9 }
果真沒有猜錯,這些方法仍是基於NavigableMap實現的,要明白其具體實現代碼,咱們來看看TreeMap中是怎麼實現NavigableMap接口中這些方法的。app
1 public Map.Entry<K,V> pollFirstEntry() { 2 // 取得當前Map第一個節點 3 Entry<K,V> p = getFirstEntry(); 4 // 返回一個只包含key、value的簡單Entry對象,exportEntry沒必要深究也很簡單 5 Map.Entry<K,V> result = exportEntry(p); 6 // 若是節點不爲空,將節點刪除 7 if (p != null) 8 deleteEntry(p); 9 return result; 10 } 11 12 public Map.Entry<K,V> pollLastEntry() { 13 // 取得當前Map第一個節點 14 Entry<K,V> p = getLastEntry(); 15 // 返回一個只包含key、value的簡單Entry對象,exportEntry沒必要深究也很簡單 16 Map.Entry<K,V> result = exportEntry(p); 17 // 若是節點不爲空,將節點刪除 18 if (p != null) 19 deleteEntry(p); 20 return result; 21 } 22 23 /** 24 * Returns the first Entry in the TreeMap (according to the TreeMap's 25 * key -sort function). Returns null if the TreeMap is empty. 26 */ 27 final Entry<K,V> getFirstEntry() { 28 // 取得根節點 29 Entry<K,V> p = root; 30 if (p != null) 31 // 循環取根節點的left,直到取到最左邊的一個節點,也就是取得最小值(紅黑樹原則最左邊最小) 32 while (p.left != null) 33 p = p. left; 34 return p; 35 } 36 37 /** 38 * Returns the last Entry in the TreeMap (according to the TreeMap's 39 * key -sort function). Returns null if the TreeMap is empty. 40 */ 41 final Entry<K,V> getLastEntry() { 42 // 取得根節點 43 Entry<K,V> p = root; 44 if (p != null) 45 // 循環取根節點的right,直到取到最右邊的一個節點,也就是取得最大值(紅黑樹原則最右邊最大) 46 while (p.right != null) 47 p = p. right; 48 return p; 49 }
在明白了紅黑樹的原則以後,這幾個取第一個和最後一個的方法看起來仍是很簡單的,咱們再來看下其餘方法的實現:jvm
1 public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, 2 K toKey, boolean toInclusive) { 3 // key越界檢查,key怎麼越界呢,固然是由於TreMap已經對key排序了,不細看 4 if (!inRange(fromKey, fromInclusive)) 5 throw new IllegalArgumentException( "fromKey out of range" ); 6 if (!inRange(toKey, toInclusive)) 7 throw new IllegalArgumentException( "toKey out of range" ); 8 // 返回AscendingSubMap對象 9 return new AscendingSubMap(m, 10 false, fromKey, fromInclusive, 11 false, toKey, toInclusive); 12 }
AscendingSubMap是NavigableSubMap子類,該構造方法直接調用NavigableSubMap,繼續看:post
1 static abstract class NavigableSubMap<K,V> extends AbstractMap<K,V> 2 implements NavigableMap<K,V>, java.io.Serializable { 3 /** 4 * The backing map. 5 */ 6 final TreeMap<K,V> m; // 底層使用原始TreeMap提供數據操做 7 8 final K lo, hi; 9 final boolean fromStart, toEnd; 10 final boolean loInclusive, hiInclusive; 11 12 13 NavigableSubMap(TreeMap<K,V> m, 14 boolean fromStart, K lo, boolean loInclusive, 15 boolean toEnd, K hi, boolean hiInclusive) { 16 if (!fromStart && !toEnd) { 17 if (m.compare(lo, hi) > 0) 18 throw new IllegalArgumentException( "fromKey > toKey" ); 19 } else { 20 if (!fromStart) // type check 21 m.compare(lo, lo); 22 if (!toEnd) 23 m.compare(hi, hi); 24 } 25 26 // 記錄邊界 27 this.m = m; 28 this.fromStart = fromStart; 29 this.lo = lo; 30 this.loInclusive = loInclusive; 31 this.toEnd = toEnd; 32 this.hi = hi; 33 this.hiInclusive = hiInclusive; 34 } 35 ... ... 36 ... ... 37 38 public final V put(K key, V value) { 39 // 邊界檢查,若是不在邊界範圍內,則拋出異常 40 if (!inRange(key)) 41 throw new IllegalArgumentException( "key out of range" ); 42 return m .put(key, value); 43 } 44 public final V get(Object key) { 45 return !inRange(key)? null : m.get(key); 46 } 47 }