這一章,我們對TreeMap進行學習。
第1部分 TreeMap介紹
TreeMap 簡介
TreeMap 是一個有序的key-value集合,它是通過紅黑樹實現的。
TreeMap繼承於AbstractMap,所以它是一個Map,即一個key-value集合。
TreeMap 實現了NavigableMap接口,意味著它支持一系列的導航方法。比如返回有序的key集合。
TreeMap 實現了Cloneable接口,意味著它能被克隆。
TreeMap 實現了java.io.Serializable接口,意味著它支持序列化。
TreeMap基於紅黑樹(Red-Black tree)實現。該映射根據其鍵的自然順序進行排序,或者根據創建映射時提供的 Comparator 進行排序,具體取決於使用的構造方法。
TreeMap的基本操作 containsKey、get、put 和 remove 的時間復雜度是 log(n) 。
另外,TreeMap是非同步的。 它的iterator 方法返回的迭代器是fail-fastl的。
TreeMap的繼承關系
java.lang.Object java.util.AbstractMap<K, V> java.util.TreeMap<K, V> public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable {}
TreeMap與Map關系如下圖:
TreeMap的構造函數
// 默認構造函數。使用該構造函數,TreeMap中的元素按照自然排序進行排列。 TreeMap() // 創建的TreeMap包含Map TreeMap(Map<? extends K, ? extends V> copyFrom) // 指定Tree的比較器 TreeMap(Comparator<? super K> comparator) // 創建的TreeSet包含copyFrom TreeMap(SortedMap<K, ? extends V> copyFrom)
TreeMap的API
Entry<K, V> ceilingEntry(K key) K ceilingKey(K key) void clear() Object clone() Comparator<? super K> comparator() boolean containsKey(Object key) NavigableSet<K> descendingKeySet() NavigableMap<K, V> descendingMap() Set<Entry<K, V>> entrySet() Entry<K, V> firstEntry() K firstKey() Entry<K, V> floorEntry(K key) K floorKey(K key) V get(Object key) NavigableMap<K, V> headMap(K to, boolean inclusive) SortedMap<K, V> headMap(K toExclusive) Entry<K, V> higherEntry(K key) K higherKey(K key) boolean isEmpty() Set<K> keySet() Entry<K, V> lastEntry() K lastKey() Entry<K, V> lowerEntry(K key) K lowerKey(K key) NavigableSet<K> navigableKeySet() Entry<K, V> pollFirstEntry() Entry<K, V> pollLastEntry() V put(K key, V value) V remove(Object key) int size() SortedMap<K, V> subMap(K fromInclusive, K toExclusive) NavigableMap<K, V> subMap(K from, boolean fromInclusive, K to, boolean toInclusive) NavigableMap<K, V> tailMap(K from, boolean inclusive) SortedMap<K, V> tailMap(K fromInclusive)
第2部分 TreeMap源碼解析
為了更了解TreeMap的原理,下面對TreeMap源碼代碼作出分析。我們先給出源碼內容,後面再對源碼進行詳細說明,當然,源碼內容中也包含了詳細的代碼注釋。讀者閱讀的時候,建議先看後面的說明,先建立一個整體印象;之後再閱讀源碼。
package java.util; public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable { // 比較器。用來給TreeMap排序 private final Comparator<? super K> comparator; // TreeMap是紅黑樹實現的,root是紅黑書的根節點 private transient Entry<K,V> root = null; // 紅黑樹的節點總數 private transient int size = 0; // 記錄紅黑樹的修改次數 private transient int modCount = 0; // 默認構造函數 public TreeMap() { comparator = null; } // 帶比較器的構造函數 public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; } // 帶Map的構造函數,Map會成為TreeMap的子集 public TreeMap(Map<? extends K, ? extends V> m) { comparator = null; putAll(m); } // 帶SortedMap的構造函數,SortedMap會成為TreeMap的子集 public TreeMap(SortedMap<K, ? extends V> m) { comparator = m.comparator(); try { buildFromSorted(m.size(), m.entrySet().iterator(), null, null); } catch (java.io.IOException cannotHappen) { } catch (ClassNotFoundException cannotHappen) { } } public int size() { return size; } // 返回TreeMap中是否保護“鍵(key)” public boolean containsKey(Object key) { return getEntry(key) != null; } // 返回TreeMap中是否保護"值(value)" public boolean containsValue(Object value) { // getFirstEntry() 是返回紅黑樹的第一個節點 // successor(e) 是獲取節點e的後繼節點 for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e)) if (valEquals(value, e.value)) return true; return false; } // 獲取“鍵(key)”對應的“值(value)” public V get(Object key) { // 獲取“鍵”為key的節點(p) Entry<K,V> p = getEntry(key); // 若節點(p)為null,返回null;否則,返回節點對應的值 return (p==null ? null : p.value); } public Comparator<? super K> comparator() { return comparator; } // 獲取第一個節點對應的key public K firstKey() { return key(getFirstEntry()); } // 獲取最後一個節點對應的key public K lastKey() { return key(getLastEntry()); } // 將map中的全部節點添加到TreeMap中 public void putAll(Map<? extends K, ? extends V> map) { // 獲取map的大小 int mapSize = map.size(); // 如果TreeMap的大小是0,且map的大小不是0,且map是已排序的“key-value對” if (size==0 && mapSize!=0 && map instanceof SortedMap) { Comparator c = ((SortedMap)map).comparator(); // 如果TreeMap和map的比較器相等; // 則將map的元素全部拷貝到TreeMap中,然後返回! if (c == comparator || (c != null && c.equals(comparator))) { ++modCount; try { buildFromSorted(mapSize, map.entrySet().iterator(), null, null); } catch (java.io.IOException cannotHappen) { } catch (ClassNotFoundException cannotHappen) { } return; } } // 調用AbstractMap中的putAll(); // AbstractMap中的putAll()又會調用到TreeMap的put() super.putAll(map); } // 獲取TreeMap中“鍵”為key的節點 final Entry<K,V> getEntry(Object key) { // 若“比較器”為null,則通過getEntryUsingComparator()獲取“鍵”為key的節點 if (comparator != null) return getEntryUsingComparator(key); if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; // 將p設為根節點 Entry<K,V> p = root; while (p != null) { int cmp = k.compareTo(p.key); // 若“p的key” < key,則p=“p的左孩子” if (cmp < 0) p = p.left; // 若“p的key” > key,則p=“p的左孩子” else if (cmp > 0) p = p.right; // 若“p的key” = key,則返回節點p else return p; } return null; } // 獲取TreeMap中“鍵”為key的節點(對應TreeMap的比較器不是null的情況) final Entry<K,V> getEntryUsingComparator(Object key) { K k = (K) key; Comparator<? super K> cpr = comparator; if (cpr != null) { // 將p設為根節點 Entry<K,V> p = root; while (p != null) { int cmp = cpr.compare(k, p.key); // 若“p的key” < key,則p=“p的左孩子” if (cmp < 0) p = p.left; // 若“p的key” > key,則p=“p的左孩子” else if (cmp > 0) p = p.right; // 若“p的key” = key,則返回節點p else return p; } } return null; } // 獲取TreeMap中不小於key的最小的節點; // 若不存在(即TreeMap中所有節點的鍵都比key大),就返回null final Entry<K,V> getCeilingEntry(K key) { Entry<K,V> p = root; while (p != null) { int cmp = compare(key, p.key); // 情況一:若“p的key” > key。 // 若 p 存在左孩子,則設 p=“p的左孩子”; // 否則,返回p if (cmp < 0) { if (p.left != null) p = p.left; else return p; // 情況二:若“p的key” < key。 } else if (cmp > 0) { // 若 p 存在右孩子,則設 p=“p的右孩子” if (p.right != null) { p = p.right; } else { // 若 p 不存在右孩子,則找出 p 的後繼節點,並返回 // 注意:這裡返回的 “p的後繼節點”有2種可能性:第一,null;第二,TreeMap中大於key的最小的節點。 // 理解這一點的核心是,getCeilingEntry是從root開始遍歷的。 // 若getCeilingEntry能走到這一步,那麼,它之前“已經遍歷過的節點的key”都 > key。 // 能理解上面所說的,那麼就很容易明白,為什麼“p的後繼節點”又2種可能性了。 Entry<K,V> parent = p.parent; Entry<K,V> ch = p; while (parent != null && ch == parent.right) { ch = parent; parent = parent.parent; } return parent; } // 情況三:若“p的key” = key。 } else return p; } return null; } // 獲取TreeMap中不大於key的最大的節點; // 若不存在(即TreeMap中所有節點的鍵都比key小),就返回null // getFloorEntry的原理和getCeilingEntry類似,這裡不再多說。 final Entry<K,V> getFloorEntry(K key) { Entry<K,V> p = root; while (p != null) { int cmp = compare(key, p.key); if (cmp > 0) { if (p.right != null) p = p.right; else return p; } else if (cmp < 0) { if (p.left != null) { p = p.left; } else { Entry<K,V> parent = p.parent; Entry<K,V> ch = p; while (parent != null && ch == parent.left) { ch = parent; parent = parent.parent; } return parent; } } else return p; } return null; } // 獲取TreeMap中大於key的最小的節點。 // 若不存在,就返回null。 // 請參照getCeilingEntry來對getHigherEntry進行理解。 final Entry<K,V> getHigherEntry(K key) { Entry<K,V> p = root; while (p != null) { int cmp = compare(key, p.key); if (cmp < 0) { if (p.left != null) p = p.left; else return p; } else { if (p.right != null) { p = p.right; } else { Entry<K,V> parent = p.parent; Entry<K,V> ch = p; while (parent != null && ch == parent.right) { ch = parent; parent = parent.parent; } return parent; } } } return null; } // 獲取TreeMap中小於key的最大的節點。 // 若不存在,就返回null。 // 請參照getCeilingEntry來對getLowerEntry進行理解。 final Entry<K,V> getLowerEntry(K key) { Entry<K,V> p = root; while (p != null) { int cmp = compare(key, p.key); if (cmp > 0) { if (p.right != null) p = p.right; else return p; } else { if (p.left != null) { p = p.left; } else { Entry<K,V> parent = p.parent; Entry<K,V> ch = p; while (parent != null && ch == parent.left) { ch = parent; parent = parent.parent; } return parent; } } } return null; } // 將“key, value”添加到TreeMap中 // 理解TreeMap的前提是掌握“紅黑樹”。 // 若理解“紅黑樹中添加節點”的算法,則很容易理解put。 public V put(K key, V value) { Entry<K,V> t = root; // 若紅黑樹為空,則插入根節點 if (t == null) { // TBD: // 5045147: (coll) Adding null to an empty TreeSet should // throw NullPointerException // // compare(key, key); // type check root = new Entry<K,V>(key, value, null); size = 1; modCount++; return null; } int cmp; Entry<K,V> parent; // split comparator and comparable paths Comparator<? super K> cpr = comparator; // 在二叉樹(紅黑樹是特殊的二叉樹)中,找到(key, value)的插入位置。 // 紅黑樹是以key來進行排序的,所以這裡以key來進行查找。 if (cpr != null) { do { parent = t; cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } else { if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; do { parent = t; cmp = k.compareTo(t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } // 新建紅黑樹的節點(e) Entry<K,V> e = new Entry<K,V>(key, value, parent); if (cmp < 0) parent.left = e; else parent.right = e; // 紅黑樹插入節點後,不再是一顆紅黑樹; // 這裡通過fixAfterInsertion的處理,來恢復紅黑樹的特性。 fixAfterInsertion(e); size++; modCount++; return null; } // 刪除TreeMap中的鍵為key的節點,並返回節點的值 public V remove(Object key) { // 找到鍵為key的節點 Entry<K,V> p = getEntry(key); if (p == null) return null; // 保存節點的值 V oldValue = p.value; // 刪除節點 deleteEntry(p); return oldValue; } // 清空紅黑樹 public void clear() { modCount++; size = 0; root = null; } // 克隆一個TreeMap,並返回Object對象 public Object clone() { TreeMap<K,V> clone = null; try { clone = (TreeMap<K,V>) super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); } // Put clone into "virgin" state (except for comparator) clone.root = null; clone.size = 0; clone.modCount = 0; clone.entrySet = null; clone.navigableKeySet = null; clone.descendingMap = null; // Initialize clone with our mappings try { clone.buildFromSorted(size, entrySet().iterator(), null, null); } catch (java.io.IOException cannotHappen) { } catch (ClassNotFoundException cannotHappen) { } return clone; } // 獲取第一個節點(對外接口)。 public Map.Entry<K,V> firstEntry() { return exportEntry(getFirstEntry()); } // 獲取最後一個節點(對外接口)。 public Map.Entry<K,V> lastEntry() { return exportEntry(getLastEntry()); } // 獲取第一個節點,並將改節點從TreeMap中刪除。 public Map.Entry<K,V> pollFirstEntry() { // 獲取第一個節點 Entry<K,V> p = getFirstEntry(); Map.Entry<K,V> result = exportEntry(p); // 刪除第一個節點 if (p != null) deleteEntry(p); return result; } // 獲取最後一個節點,並將改節點從TreeMap中刪除。 public Map.Entry<K,V> pollLastEntry() { // 獲取最後一個節點 Entry<K,V> p = getLastEntry(); Map.Entry<K,V> result = exportEntry(p); // 刪除最後一個節點 if (p != null) deleteEntry(p); return result; } // 返回小於key的最大的鍵值對,沒有的話返回null public Map.Entry<K,V> lowerEntry(K key) { return exportEntry(getLowerEntry(key)); } // 返回小於key的最大的鍵值對所對應的KEY,沒有的話返回null public K lowerKey(K key) { return keyOrNull(getLowerEntry(key)); } // 返回不大於key的最大的鍵值對,沒有的話返回null public Map.Entry<K,V> floorEntry(K key) { return exportEntry(getFloorEntry(key)); } // 返回不大於key的最大的鍵值對所對應的KEY,沒有的話返回null public K floorKey(K key) { return keyOrNull(getFloorEntry(key)); } // 返回不小於key的最小的鍵值對,沒有的話返回null public Map.Entry<K,V> ceilingEntry(K key) { return exportEntry(getCeilingEntry(key)); } // 返回不小於key的最小的鍵值對所對應的KEY,沒有的話返回null public K ceilingKey(K key) { return keyOrNull(getCeilingEntry(key)); } // 返回大於key的最小的鍵值對,沒有的話返回null public Map.Entry<K,V> higherEntry(K key) { return exportEntry(getHigherEntry(key)); } // 返回大於key的最小的鍵值對所對應的KEY,沒有的話返回null public K higherKey(K key) { return keyOrNull(getHigherEntry(key)); } // TreeMap的紅黑樹節點對應的集合 private transient EntrySet entrySet = null; // KeySet為KeySet導航類 private transient KeySet<K> navigableKeySet = null; // descendingMap為鍵值對的倒序“映射” private transient NavigableMap<K,V> descendingMap = null; // 返回TreeMap的“鍵的集合” public Set<K> keySet() { return navigableKeySet(); } // 獲取“可導航”的Key的集合 // 實際上是返回KeySet類的對象。 public NavigableSet<K> navigableKeySet() { KeySet<K> nks = navigableKeySet; return (nks != null) ? nks : (navigableKeySet = new KeySet(this)); } // 返回“TreeMap的值對應的集合” public Collection<V> values() { Collection<V> vs = values; return (vs != null) ? vs : (values = new Values()); } // 獲取TreeMap的Entry的集合,實際上是返回EntrySet類的對象。 public Set<Map.Entry<K,V>> entrySet() { EntrySet es = entrySet; return (es != null) ? es : (entrySet = new EntrySet()); } // 獲取TreeMap的降序Map // 實際上是返回DescendingSubMap類的對象 public NavigableMap<K, V> descendingMap() { NavigableMap<K, V> km = descendingMap; return (km != null) ? km : (descendingMap = new DescendingSubMap(this, true, null, true, true, null, true)); } // 獲取TreeMap的子Map // 范圍是從fromKey 到 toKey;fromInclusive是是否包含fromKey的標記,toInclusive是是否包含toKey的標記 public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { return new AscendingSubMap(this, false, fromKey, fromInclusive, false, toKey, toInclusive); } // 獲取“Map的頭部” // 范圍從第一個節點 到 toKey, inclusive是是否包含toKey的標記 public NavigableMap<K,V> headMap(K toKey, boolean inclusive) { return new AscendingSubMap(this, true, null, true, false, toKey, inclusive); } // 獲取“Map的尾部”。 // 范圍是從 fromKey 到 最後一個節點,inclusive是是否包含fromKey的標記 public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) { return new AscendingSubMap(this, false, fromKey, inclusive, true, null, true); } // 獲取“子Map”。 // 范圍是從fromKey(包括) 到 toKey(不包括) public SortedMap<K,V> subMap(K fromKey, K toKey) { return subMap(fromKey, true, toKey, false); } // 獲取“Map的頭部”。 // 范圍從第一個節點 到 toKey(不包括) public SortedMap<K,V> headMap(K toKey) { return headMap(toKey, false); } // 獲取“Map的尾部”。 // 范圍是從 fromKey(包括) 到 最後一個節點 public SortedMap<K,V> tailMap(K fromKey) { return tailMap(fromKey, true); } // ”TreeMap的值的集合“對應的類,它集成於AbstractCollection class Values extends AbstractCollection<V> { // 返回迭代器 public Iterator<V> iterator() { return new ValueIterator(getFirstEntry()); } // 返回個數 public int size() { return TreeMap.this.size(); } // "TreeMap的值的集合"中是否包含"對象o" public boolean contains(Object o) { return TreeMap.this.containsValue(o); } // 刪除"TreeMap的值的集合"中的"對象o" public boolean remove(Object o) { for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e)) { if (valEquals(e.getValue(), o)) { deleteEntry(e); return true; } } return false; } // 清空刪除"TreeMap的值的集合" public void clear() { TreeMap.this.clear(); } } // EntrySet是“TreeMap的所有鍵值對組成的集合”, // EntrySet集合的單位是單個“鍵值對”。 class EntrySet extends AbstractSet<Map.Entry<K,V>> { public Iterator<Map.Entry<K,V>> iterator() { return new EntryIterator(getFirstEntry()); } // EntrySet中是否包含“鍵值對Object” public boolean contains(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<K,V> entry = (Map.Entry<K,V>) o; V value = entry.getValue(); Entry<K,V> p = getEntry(entry.getKey()); return p != null && valEquals(p.getValue(), value); } // 刪除EntrySet中的“鍵值對Object” public boolean remove(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<K,V> entry = (Map.Entry<K,V>) o; V value = entry.getValue(); Entry<K,V> p = getEntry(entry.getKey()); if (p != null && valEquals(p.getValue(), value)) { deleteEntry(p); return true; } return false; } // 返回EntrySet中元素個數 public int size() { return TreeMap.this.size(); } // 清空EntrySet public void clear() { TreeMap.this.clear(); } } // 返回“TreeMap的KEY組成的迭代器(順序)” Iterator<K> keyIterator() { return new KeyIterator(getFirstEntry()); } // 返回“TreeMap的KEY組成的迭代器(逆序)” Iterator<K> descendingKeyIterator() { return new DescendingKeyIterator(getLastEntry()); } // KeySet是“TreeMap中所有的KEY組成的集合” // KeySet繼承於AbstractSet,而且實現了NavigableSet接口。 static final class KeySet<E> extends AbstractSet<E> implements NavigableSet<E> { // NavigableMap成員,KeySet是通過NavigableMap實現的 private final NavigableMap<E, Object> m; KeySet(NavigableMap<E,Object> map) { m = map; } // 升序迭代器 public Iterator<E> iterator() { // 若是TreeMap對象,則調用TreeMap的迭代器keyIterator() // 否則,調用TreeMap子類NavigableSubMap的迭代器keyIterator() if (m instanceof TreeMap) return ((TreeMap<E,Object>)m).keyIterator(); else return (Iterator<E>)(((TreeMap.NavigableSubMap)m).keyIterator()); } // 降序迭代器 public Iterator<E> descendingIterator() { // 若是TreeMap對象,則調用TreeMap的迭代器descendingKeyIterator() // 否則,調用TreeMap子類NavigableSubMap的迭代器descendingKeyIterator() if (m instanceof TreeMap) return ((TreeMap<E,Object>)m).descendingKeyIterator(); else return (Iterator<E>)(((TreeMap.NavigableSubMap)m).descendingKeyIterator()); } public int size() { return m.size(); } public boolean isEmpty() { return m.isEmpty(); } public boolean contains(Object o) { return m.containsKey(o); } public void clear() { m.clear(); } public E lower(E e) { return m.lowerKey(e); } public E floor(E e) { return m.floorKey(e); } public E ceiling(E e) { return m.ceilingKey(e); } public E higher(E e) { return m.higherKey(e); } public E first() { return m.firstKey(); } public E last() { return m.lastKey(); } public Comparator<? super E> comparator() { return m.comparator(); } public E pollFirst() { Map.Entry<E,Object> e = m.pollFirstEntry(); return e == null? null : e.getKey(); } public E pollLast() { Map.Entry<E,Object> e = m.pollLastEntry(); return e == null? null : e.getKey(); } public boolean remove(Object o) { int oldSize = size(); m.remove(o); return size() != oldSize; } public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { return new TreeSet<E>(m.subMap(fromElement, fromInclusive, toElement, toInclusive)); } public NavigableSet<E> headSet(E toElement, boolean inclusive) { return new TreeSet<E>(m.headMap(toElement, inclusive)); } public NavigableSet<E> tailSet(E fromElement, boolean inclusive) { return new TreeSet<E>(m.tailMap(fromElement, inclusive)); } public SortedSet<E> subSet(E fromElement, E toElement) { return subSet(fromElement, true, toElement, false); } public SortedSet<E> headSet(E toElement) { return headSet(toElement, false); } public SortedSet<E> tailSet(E fromElement) { return tailSet(fromElement, true); } public NavigableSet<E> descendingSet() { return new TreeSet(m.descendingMap()); } } // 它是TreeMap中的一個抽象迭代器,實現了一些通用的接口。 abstract class PrivateEntryIterator<T> implements Iterator<T> { // 下一個元素 Entry<K,V> next; // 上一次返回元素 Entry<K,V> lastReturned; // 期望的修改次數,用於實現fast-fail機制 int expectedModCount; PrivateEntryIterator(Entry<K,V> first) { expectedModCount = modCount; lastReturned = null; next = first; } public final boolean hasNext() { return next != null; } // 獲取下一個節點 final Entry<K,V> nextEntry() { Entry<K,V> e = next; if (e == null) throw new NoSuchElementException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); next = successor(e); lastReturned = e; return e; } // 獲取上一個節點 final Entry<K,V> prevEntry() { Entry<K,V> e = next; if (e == null) throw new NoSuchElementException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); next = predecessor(e); lastReturned = e; return e; } // 刪除當前節點 public void remove() { if (lastReturned == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); // 這裡重點強調一下“為什麼當lastReturned的左右孩子都不為空時,要將其賦值給next”。 // 目的是為了“刪除lastReturned節點之後,next節點指向的仍然是下一個節點”。 // 根據“紅黑樹”的特性可知: // 當被刪除節點有兩個兒子時。那麼,首先把“它的後繼節點的內容”復制給“該節點的內容”;之後,刪除“它的後繼節點”。 // 這意味著“當被刪除節點有兩個兒子時,刪除當前節點之後,'新的當前節點'實際上是‘原有的後繼節點(即下一個節點)’”。 // 而此時next仍然指向"新的當前節點"。也就是說next是仍然是指向下一個節點;能繼續遍歷紅黑樹。 if (lastReturned.left != null && lastReturned.right != null) next = lastReturned; deleteEntry(lastReturned); expectedModCount = modCount; lastReturned = null; } } // TreeMap的Entry對應的迭代器 final class EntryIterator extends PrivateEntryIterator<Map.Entry<K,V>> { EntryIterator(Entry<K,V> first) { super(first); } public Map.Entry<K,V> next() { return nextEntry(); } } // TreeMap的Value對應的迭代器 final class ValueIterator extends PrivateEntryIterator<V> { ValueIterator(Entry<K,V> first) { super(first); } public V next() { return nextEntry().value; } } // reeMap的KEY組成的迭代器(順序) final class KeyIterator extends PrivateEntryIterator<K> { KeyIterator(Entry<K,V> first) { super(first); } public K next() { return nextEntry().key; } } // TreeMap的KEY組成的迭代器(逆序) final class DescendingKeyIterator extends PrivateEntryIterator<K> { DescendingKeyIterator(Entry<K,V> first) { super(first); } public K next() { return prevEntry().key; } } // 比較兩個對象的大小 final int compare(Object k1, Object k2) { return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2) : comparator.compare((K)k1, (K)k2); } // 判斷兩個對象是否相等 final static boolean valEquals(Object o1, Object o2) { return (o1==null ? o2==null : o1.equals(o2)); } // 返回“Key-Value鍵值對”的一個簡單拷貝(AbstractMap.SimpleImmutableEntry<K,V>對象) // 可用來讀取“鍵值對”的值 static <K,V> Map.Entry<K,V> exportEntry(TreeMap.Entry<K,V> e) { return e == null? null : new AbstractMap.SimpleImmutableEntry<K,V>(e); } // 若“鍵值對”不為null,則返回KEY;否則,返回null static <K,V> K keyOrNull(TreeMap.Entry<K,V> e) { return e == null? null : e.key; } // 若“鍵值對”不為null,則返回KEY;否則,拋出異常 static <K> K key(Entry<K,?> e) { if (e==null) throw new NoSuchElementException(); return e.key; } // TreeMap的SubMap,它一個抽象類,實現了公共操作。 // 它包括了"(升序)AscendingSubMap"和"(降序)DescendingSubMap"兩個子類。 static abstract class NavigableSubMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, java.io.Serializable { // TreeMap的拷貝 final TreeMap<K,V> m; // lo是“子Map范圍的最小值”,hi是“子Map范圍的最大值”; // loInclusive是“是否包含lo的標記”,hiInclusive是“是否包含hi的標記” // fromStart是“表示是否從第一個節點開始計算”, // toEnd是“表示是否計算到最後一個節點 ” final K lo, hi; final boolean fromStart, toEnd; final boolean loInclusive, hiInclusive; // 構造函數 NavigableSubMap(TreeMap<K,V> m, boolean fromStart, K lo, boolean loInclusive, boolean toEnd, K hi, boolean hiInclusive) { if (!fromStart && !toEnd) { if (m.compare(lo, hi) > 0) throw new IllegalArgumentException("fromKey > toKey"); } else { if (!fromStart) // type check m.compare(lo, lo); if (!toEnd) m.compare(hi, hi); } this.m = m; this.fromStart = fromStart; this.lo = lo; this.loInclusive = loInclusive; this.toEnd = toEnd; this.hi = hi; this.hiInclusive = hiInclusive; } // 判斷key是否太小 final boolean tooLow(Object key) { // 若該SubMap不包括“起始節點”, // 並且,“key小於最小鍵(lo)”或者“key等於最小鍵(lo),但最小鍵卻沒包括在該SubMap內” // 則判斷key太小。其余情況都不是太小! if (!fromStart) { int c = m.compare(key, lo); if (c < 0 || (c == 0 && !loInclusive)) return true; } return false; } // 判斷key是否太大 final boolean tooHigh(Object key) { // 若該SubMap不包括“結束節點”, // 並且,“key大於最大鍵(hi)”或者“key等於最大鍵(hi),但最大鍵卻沒包括在該SubMap內” // 則判斷key太大。其余情況都不是太大! if (!toEnd) { int c = m.compare(key, hi); if (c > 0 || (c == 0 && !hiInclusive)) return true; } return false; } // 判斷key是否在“lo和hi”開區間范圍內 final boolean inRange(Object key) { return !tooLow(key) && !tooHigh(key); } // 判斷key是否在封閉區間內 final boolean inClosedRange(Object key) { return (fromStart || m.compare(key, lo) >= 0) && (toEnd || m.compare(hi, key) >= 0); } // 判斷key是否在區間內, inclusive是區間開關標志 final boolean inRange(Object key, boolean inclusive) { return inclusive ? inRange(key) : inClosedRange(key); } // 返回最低的Entry final TreeMap.Entry<K,V> absLowest() { // 若“包含起始節點”,則調用getFirstEntry()返回第一個節點 // 否則的話,若包括lo,則調用getCeilingEntry(lo)獲取大於/等於lo的最小的Entry; // 否則,調用getHigherEntry(lo)獲取大於lo的最小Entry TreeMap.Entry<K,V> e = (fromStart ? m.getFirstEntry() : (loInclusive ? m.getCeilingEntry(lo) : m.getHigherEntry(lo))); return (e == null || tooHigh(e.key)) ? null : e; } // 返回最高的Entry final TreeMap.Entry<K,V> absHighest() { // 若“包含結束節點”,則調用getLastEntry()返回最後一個節點 // 否則的話,若包括hi,則調用getFloorEntry(hi)獲取小於/等於hi的最大的Entry; // 否則,調用getLowerEntry(hi)獲取大於hi的最大Entry TreeMap.Entry<K,V> e = TreeMap.Entry<K,V> e = (toEnd ? m.getLastEntry() : (hiInclusive ? m.getFloorEntry(hi) : m.getLowerEntry(hi))); return (e == null || tooLow(e.key)) ? null : e; } // 返回"大於/等於key的最小的Entry" final TreeMap.Entry<K,V> absCeiling(K key) { // 只有在“key太小”的情況下,absLowest()返回的Entry才是“大於/等於key的最小Entry” // 其它情況下不行。例如,當包含“起始節點”時,absLowest()返回的是最小Entry了! if (tooLow(key)) return absLowest(); // 獲取“大於/等於key的最小Entry” TreeMap.Entry<K,V> e = m.getCeilingEntry(key); return (e == null || tooHigh(e.key)) ? null : e; } // 返回"大於key的最小的Entry" final TreeMap.Entry<K,V> absHigher(K key) { // 只有在“key太小”的情況下,absLowest()返回的Entry才是“大於key的最小Entry” // 其它情況下不行。例如,當包含“起始節點”時,absLowest()返回的是最小Entry了,而不一定是“大於key的最小Entry”! if (tooLow(key)) return absLowest(); // 獲取“大於key的最小Entry” TreeMap.Entry<K,V> e = m.getHigherEntry(key); return (e == null || tooHigh(e.key)) ? null : e; } // 返回"小於/等於key的最大的Entry" final TreeMap.Entry<K,V> absFloor(K key) { // 只有在“key太大”的情況下,(absHighest)返回的Entry才是“小於/等於key的最大Entry” // 其它情況下不行。例如,當包含“結束節點”時,absHighest()返回的是最大Entry了! if (tooHigh(key)) return absHighest(); // 獲取"小於/等於key的最大的Entry" TreeMap.Entry<K,V> e = m.getFloorEntry(key); return (e == null || tooLow(e.key)) ? null : e; } // 返回"小於key的最大的Entry" final TreeMap.Entry<K,V> absLower(K key) { // 只有在“key太大”的情況下,(absHighest)返回的Entry才是“小於key的最大Entry” // 其它情況下不行。例如,當包含“結束節點”時,absHighest()返回的是最大Entry了,而不一定是“小於key的最大Entry”! if (tooHigh(key)) return absHighest(); // 獲取"小於key的最大的Entry" TreeMap.Entry<K,V> e = m.getLowerEntry(key); return (e == null || tooLow(e.key)) ? null : e; } // 返回“大於最大節點中的最小節點”,不存在的話,返回null final TreeMap.Entry<K,V> absHighFence() { return (toEnd ? null : (hiInclusive ? m.getHigherEntry(hi) : m.getCeilingEntry(hi))); } // 返回“小於最小節點中的最大節點”,不存在的話,返回null final TreeMap.Entry<K,V> absLowFence() { return (fromStart ? null : (loInclusive ? m.getLowerEntry(lo) : m.getFloorEntry(lo))); } // 下面幾個abstract方法是需要NavigableSubMap的實現類實現的方法 abstract TreeMap.Entry<K,V> subLowest(); abstract TreeMap.Entry<K,V> subHighest(); abstract TreeMap.Entry<K,V> subCeiling(K key); abstract TreeMap.Entry<K,V> subHigher(K key); abstract TreeMap.Entry<K,V> subFloor(K key); abstract TreeMap.Entry<K,V> subLower(K key); // 返回“順序”的鍵迭代器 abstract Iterator<K> keyIterator(); // 返回“逆序”的鍵迭代器 abstract Iterator<K> descendingKeyIterator(); // 返回SubMap是否為空。空的話,返回true,否則返回false public boolean isEmpty() { return (fromStart && toEnd) ? m.isEmpty() : entrySet().isEmpty(); } // 返回SubMap的大小 public int size() { return (fromStart && toEnd) ? m.size() : entrySet().size(); } // 返回SubMap是否包含鍵key public final boolean containsKey(Object key) { return inRange(key) && m.containsKey(key); } // 將key-value 插入SubMap中 public final V put(K key, V value) { if (!inRange(key)) throw new IllegalArgumentException("key out of range"); return m.put(key, value); } // 獲取key對應值 public final V get(Object key) { return !inRange(key)? null : m.get(key); } // 刪除key對應的鍵值對 public final V remove(Object key) { return !inRange(key)? null : m.remove(key); } // 獲取“大於/等於key的最小鍵值對” public final Map.Entry<K,V> ceilingEntry(K key) { return exportEntry(subCeiling(key)); } // 獲取“大於/等於key的最小鍵” public final K ceilingKey(K key) { return keyOrNull(subCeiling(key)); } // 獲取“大於key的最小鍵值對” public final Map.Entry<K,V> higherEntry(K key) { return exportEntry(subHigher(key)); } // 獲取“大於key的最小鍵” public final K higherKey(K key) { return keyOrNull(subHigher(key)); } // 獲取“小於/等於key的最大鍵值對” public final Map.Entry<K,V> floorEntry(K key) { return exportEntry(subFloor(key)); } // 獲取“小於/等於key的最大鍵” public final K floorKey(K key) { return keyOrNull(subFloor(key)); } // 獲取“小於key的最大鍵值對” public final Map.Entry<K,V> lowerEntry(K key) { return exportEntry(subLower(key)); } // 獲取“小於key的最大鍵” public final K lowerKey(K key) { return keyOrNull(subLower(key)); } // 獲取"SubMap的第一個鍵" public final K firstKey() { return key(subLowest()); } // 獲取"SubMap的最後一個鍵" public final K lastKey() { return key(subHighest()); } // 獲取"SubMap的第一個鍵值對" public final Map.Entry<K,V> firstEntry() { return exportEntry(subLowest()); } // 獲取"SubMap的最後一個鍵值對" public final Map.Entry<K,V> lastEntry() { return exportEntry(subHighest()); } // 返回"SubMap的第一個鍵值對",並從SubMap中刪除改鍵值對 public final Map.Entry<K,V> pollFirstEntry() { TreeMap.Entry<K,V> e = subLowest(); Map.Entry<K,V> result = exportEntry(e); if (e != null) m.deleteEntry(e); return result; } // 返回"SubMap的最後一個鍵值對",並從SubMap中刪除改鍵值對 public final Map.Entry<K,V> pollLastEntry() { TreeMap.Entry<K,V> e = subHighest(); Map.Entry<K,V> result = exportEntry(e); if (e != null) m.deleteEntry(e); return result; } // Views transient NavigableMap<K,V> descendingMapView = null; transient EntrySetView entrySetView = null; transient KeySet<K> navigableKeySetView = null; // 返回NavigableSet對象,實際上返回的是當前對象的"Key集合"。 public final NavigableSet<K> navigableKeySet() { KeySet<K> nksv = navigableKeySetView; return (nksv != null) ? nksv : (navigableKeySetView = new TreeMap.KeySet(this)); } // 返回"Key集合"對象 public final Set<K> keySet() { return navigableKeySet(); } // 返回“逆序”的Key集合 public NavigableSet<K> descendingKeySet() { return descendingMap().navigableKeySet(); } // 排列fromKey(包含) 到 toKey(不包含) 的子map public final SortedMap<K,V> subMap(K fromKey, K toKey) { return subMap(fromKey, true, toKey, false); } // 返回當前Map的頭部(從第一個節點 到 toKey, 不包括toKey) public final SortedMap<K,V> headMap(K toKey) { return headMap(toKey, false); } // 返回當前Map的尾部[從 fromKey(包括fromKeyKey) 到 最後一個節點] public final SortedMap<K,V> tailMap(K fromKey) { return tailMap(fromKey, true); } // Map的Entry的集合 abstract class EntrySetView extends AbstractSet<Map.Entry<K,V>> { private transient int size = -1, sizeModCount; // 獲取EntrySet的大小 public int size() { // 若SubMap是從“開始節點”到“結尾節點”,則SubMap大小就是原TreeMap的大小 if (fromStart && toEnd) return m.size(); // 若SubMap不是從“開始節點”到“結尾節點”,則調用iterator()遍歷EntrySetView中的元素 if (size == -1 || sizeModCount != m.modCount) { sizeModCount = m.modCount; size = 0; Iterator i = iterator(); while (i.hasNext()) { size++; i.next(); } } return size; } // 判斷EntrySetView是否為空 public boolean isEmpty() { TreeMap.Entry<K,V> n = absLowest(); return n == null || tooHigh(n.key); } // 判斷EntrySetView是否包含Object public boolean contains(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<K,V> entry = (Map.Entry<K,V>) o; K key = entry.getKey(); if (!inRange(key)) return false; TreeMap.Entry node = m.getEntry(key); return node != null && valEquals(node.getValue(), entry.getValue()); } // 從EntrySetView中刪除Object public boolean remove(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<K,V> entry = (Map.Entry<K,V>) o; K key = entry.getKey(); if (!inRange(key)) return false; TreeMap.Entry<K,V> node = m.getEntry(key); if (node!=null && valEquals(node.getValue(),entry.getValue())){ m.deleteEntry(node); return true; } return false; } } // SubMap的迭代器 abstract class SubMapIterator<T> implements Iterator<T> { // 上一次被返回的Entry TreeMap.Entry<K,V> lastReturned; // 指向下一個Entry TreeMap.Entry<K,V> next; // “柵欄key”。根據SubMap是“升序”還是“降序”具有不同的意義 final K fenceKey; int expectedModCount; // 構造函數 SubMapIterator(TreeMap.Entry<K,V> first, TreeMap.Entry<K,V> fence) { // 每創建一個SubMapIterator時,保存修改次數 // 若後面發現expectedModCount和modCount不相等,則拋出ConcurrentModificationException異常。 // 這就是所說的fast-fail機制的原理! expectedModCount = m.modCount; lastReturned = null; next = first; fenceKey = fence == null ? null : fence.key; } // 是否存在下一個Entry public final boolean hasNext() { return next != null && next.key != fenceKey; } // 返回下一個Entry final TreeMap.Entry<K,V> nextEntry() { TreeMap.Entry<K,V> e = next; if (e == null || e.key == fenceKey) throw new NoSuchElementException(); if (m.modCount != expectedModCount) throw new ConcurrentModificationException(); // next指向e的後繼節點 next = successor(e); lastReturned = e; return e; } // 返回上一個Entry final TreeMap.Entry<K,V> prevEntry() { TreeMap.Entry<K,V> e = next; if (e == null || e.key == fenceKey) throw new NoSuchElementException(); if (m.modCount != expectedModCount) throw new ConcurrentModificationException(); // next指向e的前繼節點 next = predecessor(e); lastReturned = e; return e; } // 刪除當前節點(用於“升序的SubMap”)。 // 刪除之後,可以繼續升序遍歷;紅黑樹特性沒變。 final void removeAscending() { if (lastReturned == null) throw new IllegalStateException(); if (m.modCount != expectedModCount) throw new ConcurrentModificationException(); // 這裡重點強調一下“為什麼當lastReturned的左右孩子都不為空時,要將其賦值給next”。 // 目的是為了“刪除lastReturned節點之後,next節點指向的仍然是下一個節點”。 // 根據“紅黑樹”的特性可知: // 當被刪除節點有兩個兒子時。那麼,首先把“它的後繼節點的內容”復制給“該節點的內容”;之後,刪除“它的後繼節點”。 // 這意味著“當被刪除節點有兩個兒子時,刪除當前節點之後,'新的當前節點'實際上是‘原有的後繼節點(即下一個節點)’”。 // 而此時next仍然指向"新的當前節點"。也就是說next是仍然是指向下一個節點;能繼續遍歷紅黑樹。 if (lastReturned.left != null && lastReturned.right != null) next = lastReturned; m.deleteEntry(lastReturned); lastReturned = null; expectedModCount = m.modCount; } // 刪除當前節點(用於“降序的SubMap”)。 // 刪除之後,可以繼續降序遍歷;紅黑樹特性沒變。 final void removeDescending() { if (lastReturned == null) throw new IllegalStateException(); if (m.modCount != expectedModCount) throw new ConcurrentModificationException(); m.deleteEntry(lastReturned); lastReturned = null; expectedModCount = m.modCount; } } // SubMap的Entry迭代器,它只支持升序操作,繼承於SubMapIterator final class SubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> { SubMapEntryIterator(TreeMap.Entry<K,V> first, TreeMap.Entry<K,V> fence) { super(first, fence); } // 獲取下一個節點(升序) public Map.Entry<K,V> next() { return nextEntry(); } // 刪除當前節點(升序) public void remove() { removeAscending(); } } // SubMap的Key迭代器,它只支持升序操作,繼承於SubMapIterator final class SubMapKeyIterator extends SubMapIterator<K> { SubMapKeyIterator(TreeMap.Entry<K,V> first, TreeMap.Entry<K,V> fence) { super(first, fence); } // 獲取下一個節點(升序) public K next() { return nextEntry().key; } // 刪除當前節點(升序) public void remove() { removeAscending(); } } // 降序SubMap的Entry迭代器,它只支持降序操作,繼承於SubMapIterator final class DescendingSubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> { DescendingSubMapEntryIterator(TreeMap.Entry<K,V> last, TreeMap.Entry<K,V> fence) { super(last, fence); } // 獲取下一個節點(降序) public Map.Entry<K,V> next() { return prevEntry(); } // 刪除當前節點(降序) public void remove() { removeDescending(); } } // 降序SubMap的Key迭代器,它只支持降序操作,繼承於SubMapIterator final class DescendingSubMapKeyIterator extends SubMapIterator<K> { DescendingSubMapKeyIterator(TreeMap.Entry<K,V> last, TreeMap.Entry<K,V> fence) { super(last, fence); } // 獲取下一個節點(降序) public K next() { return prevEntry().key; } // 刪除當前節點(降序) public void remove() { removeDescending(); } } } // 升序的SubMap,繼承於NavigableSubMap static final class AscendingSubMap<K,V> extends NavigableSubMap<K,V> { private static final long serialVersionUID = 912986545866124060L; // 構造函數 AscendingSubMap(TreeMap<K,V> m, boolean fromStart, K lo, boolean loInclusive, boolean toEnd, K hi, boolean hiInclusive) { super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive); } // 比較器 public Comparator<? super K> comparator() { return m.comparator(); } // 獲取“子Map”。 // 范圍是從fromKey 到 toKey;fromInclusive是是否包含fromKey的標記,toInclusive是是否包含toKey的標記 public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { if (!inRange(fromKey, fromInclusive)) throw new IllegalArgumentException("fromKey out of range"); if (!inRange(toKey, toInclusive)) throw new IllegalArgumentException("toKey out of range"); return new AscendingSubMap(m, false, fromKey, fromInclusive, false, toKey, toInclusive); } // 獲取“Map的頭部”。 // 范圍從第一個節點 到 toKey, inclusive是是否包含toKey的標記 public NavigableMap<K,V> headMap(K toKey, boolean inclusive) { if (!inRange(toKey, inclusive)) throw new IllegalArgumentException("toKey out of range"); return new AscendingSubMap(m, fromStart, lo, loInclusive, false, toKey, inclusive); } // 獲取“Map的尾部”。 // 范圍是從 fromKey 到 最後一個節點,inclusive是是否包含fromKey的標記 public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive){ if (!inRange(fromKey, inclusive)) throw new IllegalArgumentException("fromKey out of range"); return new AscendingSubMap(m, false, fromKey, inclusive, toEnd, hi, hiInclusive); } // 獲取對應的降序Map public NavigableMap<K,V> descendingMap() { NavigableMap<K,V> mv = descendingMapView; return (mv != null) ? mv : (descendingMapView = new DescendingSubMap(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive)); } // 返回“升序Key迭代器” Iterator<K> keyIterator() { return new SubMapKeyIterator(absLowest(), absHighFence()); } // 返回“降序Key迭代器” Iterator<K> descendingKeyIterator() { return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); } // “升序EntrySet集合”類 // 實現了iterator() final class AscendingEntrySetView extends EntrySetView { public Iterator<Map.Entry<K,V>> iterator() { return new SubMapEntryIterator(absLowest(), absHighFence()); } } // 返回“升序EntrySet集合” public Set<Map.Entry<K,V>> entrySet() { EntrySetView es = entrySetView; return (es != null) ? es : new AscendingEntrySetView(); } TreeMap.Entry<K,V> subLowest() { return absLowest(); } TreeMap.Entry<K,V> subHighest() { return absHighest(); } TreeMap.Entry<K,V> subCeiling(K key) { return absCeiling(key); } TreeMap.Entry<K,V> subHigher(K key) { return absHigher(key); } TreeMap.Entry<K,V> subFloor(K key) { return absFloor(key); } TreeMap.Entry<K,V> subLower(K key) { return absLower(key); } } // 降序的SubMap,繼承於NavigableSubMap // 相比於升序SubMap,它的實現機制是將“SubMap的比較器反轉”! static final class DescendingSubMap<K,V> extends NavigableSubMap<K,V> { private static final long serialVersionUID = 912986545866120460L; DescendingSubMap(TreeMap<K,V> m, boolean fromStart, K lo, boolean loInclusive, boolean toEnd, K hi, boolean hiInclusive) { super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive); } // 反轉的比較器:是將原始比較器反轉得到的。 private final Comparator<? super K> reverseComparator = Collections.reverseOrder(m.comparator); // 獲取反轉比較器 public Comparator<? super K> comparator() { return reverseComparator; } // 獲取“子Map”。 // 范圍是從fromKey 到 toKey;fromInclusive是是否包含fromKey的標記,toInclusive是是否包含toKey的標記 public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { if (!inRange(fromKey, fromInclusive)) throw new IllegalArgumentException("fromKey out of range"); if (!inRange(toKey, toInclusive)) throw new IllegalArgumentException("toKey out of range"); return new DescendingSubMap(m, false, toKey, toInclusive, false, fromKey, fromInclusive); } // 獲取“Map的頭部”。 // 范圍從第一個節點 到 toKey, inclusive是是否包含toKey的標記 public NavigableMap<K,V> headMap(K toKey, boolean inclusive) { if (!inRange(toKey, inclusive)) throw new IllegalArgumentException("toKey out of range"); return new DescendingSubMap(m, false, toKey, inclusive, toEnd, hi, hiInclusive); } // 獲取“Map的尾部”。 // 范圍是從 fromKey 到 最後一個節點,inclusive是是否包含fromKey的標記 public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive){ if (!inRange(fromKey, inclusive)) throw new IllegalArgumentException("fromKey out of range"); return new DescendingSubMap(m, fromStart, lo, loInclusive, false, fromKey, inclusive); } // 獲取對應的降序Map public NavigableMap<K,V> descendingMap() { NavigableMap<K,V> mv = descendingMapView; return (mv != null) ? mv : (descendingMapView = new AscendingSubMap(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive)); } // 返回“升序Key迭代器” Iterator<K> keyIterator() { return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); } // 返回“降序Key迭代器” Iterator<K> descendingKeyIterator() { return new SubMapKeyIterator(absLowest(), absHighFence()); } // “降序EntrySet集合”類 // 實現了iterator() final class DescendingEntrySetView extends EntrySetView { public Iterator<Map.Entry<K,V>> iterator() { return new DescendingSubMapEntryIterator(absHighest(), absLowFence()); } } // 返回“降序EntrySet集合” public Set<Map.Entry<K,V>> entrySet() { EntrySetView es = entrySetView; return (es != null) ? es : new DescendingEntrySetView(); } TreeMap.Entry<K,V> subLowest() { return absHighest(); } TreeMap.Entry<K,V> subHighest() { return absLowest(); } TreeMap.Entry<K,V> subCeiling(K key) { return absFloor(key); } TreeMap.Entry<K,V> subHigher(K key) { return absLower(key); } TreeMap.Entry<K,V> subFloor(K key) { return absCeiling(key); } TreeMap.Entry<K,V> subLower(K key) { return absHigher(key); } } // SubMap是舊版本的類,新的Java中沒有用到。 private class SubMap extends AbstractMap<K,V> implements SortedMap<K,V>, java.io.Serializable { private static final long serialVersionUID = -6520786458950516097L; private boolean fromStart = false, toEnd = false; private K fromKey, toKey; private Object readResolve() { return new AscendingSubMap(TreeMap.this, fromStart, fromKey, true, toEnd, toKey, false); } public Set<Map.Entry<K,V>> entrySet() { throw new InternalError(); } public K lastKey() { throw new InternalError(); } public K firstKey() { throw new InternalError(); } public SortedMap<K,V> subMap(K fromKey, K toKey) { throw new InternalError(); } public SortedMap<K,V> headMap(K toKey) { throw new InternalError(); } public SortedMap<K,V> tailMap(K fromKey) { throw new InternalError(); } public Comparator<? super K> comparator() { throw new InternalError(); } } // 紅黑樹的節點顏色--紅色 private static final boolean RED = false; // 紅黑樹的節點顏色--黑色 private static final boolean BLACK = true; // “紅黑樹的節點”對應的類。 // 包含了 key(鍵)、value(值)、left(左孩子)、right(右孩子)、parent(父節點)、color(顏色) static final class Entry<K,V> implements Map.Entry<K,V> { // 鍵 K key; // 值 V value; // 左孩子 Entry<K,V> left = null; // 右孩子 Entry<K,V> right = null; // 父節點 Entry<K,V> parent; // 當前節點顏色 boolean color = BLACK; // 構造函數 Entry(K key, V value, Entry<K,V> parent) { this.key = key; this.value = value; this.parent = parent; } // 返回“鍵” public K getKey() { return key; } // 返回“值” public V getValue() { return value; } // 更新“值”,返回舊的值 public V setValue(V value) { V oldValue = this.value; this.value = value; return oldValue; } // 判斷兩個節點是否相等的函數,覆蓋equals()函數。 // 若兩個節點的“key相等”並且“value相等”,則兩個節點相等 public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<?,?> e = (Map.Entry<?,?>)o; return valEquals(key,e.getKey()) && valEquals(value,e.getValue()); } // 覆蓋hashCode函數。 public int hashCode() { int keyHash = (key==null ? 0 : key.hashCode()); int valueHash = (value==null ? 0 : value.hashCode()); return keyHash ^ valueHash; } // 覆蓋toString()函數。 public String toString() { return key + "=" + value; } } // 返回“紅黑樹的第一個節點” final Entry<K,V> getFirstEntry() { Entry<K,V> p = root; if (p != null) while (p.left != null) p = p.left; return p; } // 返回“紅黑樹的最後一個節點” final Entry<K,V> getLastEntry() { Entry<K,V> p = root; if (p != null) while (p.right != null) p = p.right; return p; } // 返回“節點t的後繼節點” static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) { if (t == null) return null; else if (t.right != null) { Entry<K,V> p = t.right; while (p.left != null) p = p.left; return p; } else { Entry<K,V> p = t.parent; Entry<K,V> ch = t; while (p != null && ch == p.right) { ch = p; p = p.parent; } return p; } } // 返回“節點t的前繼節點” static <K,V> Entry<K,V> predecessor(Entry<K,V> t) { if (t == null) return null; else if (t.left != null) { Entry<K,V> p = t.left; while (p.right != null) p = p.right; return p; } else { Entry<K,V> p = t.parent; Entry<K,V> ch = t; while (p != null && ch == p.left) { ch = p; p = p.parent; } return p; } } // 返回“節點p的顏色” // 根據“紅黑樹的特性”可知:空節點顏色是黑色。 private static <K,V> boolean colorOf(Entry<K,V> p) { return (p == null ? BLACK : p.color); } // 返回“節點p的父節點” private static <K,V> Entry<K,V> parentOf(Entry<K,V> p) { return (p == null ? null: p.parent); } // 設置“節點p的顏色為c” private static <K,V> void setColor(Entry<K,V> p, boolean c) { if (p != null) p.color = c; } // 設置“節點p的左孩子” private static <K,V> Entry<K,V> leftOf(Entry<K,V> p) { return (p == null) ? null: p.left; } // 設置“節點p的右孩子” private static <K,V> Entry<K,V> rightOf(Entry<K,V> p) { return (p == null) ? null: p.right; } // 對節點p執行“左旋”操作 private void rotateLeft(Entry<K,V> p) { if (p != null) { Entry<K,V> r = p.right; p.right = r.left; if (r.left != null) r.left.parent = p; r.parent = p.parent; if (p.parent == null) root = r; else if (p.parent.left == p) p.parent.left = r; else p.parent.right = r; r.left = p; p.parent = r; } } // 對節點p執行“右旋”操作 private void rotateRight(Entry<K,V> p) { if (p != null) { Entry<K,V> l = p.left; p.left = l.right; if (l.right != null) l.right.parent = p; l.parent = p.parent; if (p.parent == null) root = l; else if (p.parent.right == p) p.parent.right = l; else p.parent.left = l; l.right = p; p.parent = l; } } // 插入之後的修正操作。 // 目的是保證:紅黑樹插入節點之後,仍然是一顆紅黑樹 private void fixAfterInsertion(Entry<K,V> x) { x.color = RED; while (x != null && x != root && x.parent.color == RED) { if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { Entry<K,V> y = rightOf(parentOf(parentOf(x))); if (colorOf(y) == RED) { setColor(parentOf(x), BLACK); setColor(y, BLACK); setColor(parentOf(parentOf(x)), RED); x = parentOf(parentOf(x)); } else { if (x == rightOf(parentOf(x))) { x = parentOf(x); rotateLeft(x); } setColor(parentOf(x), BLACK); setColor(parentOf(parentOf(x)), RED); rotateRight(parentOf(parentOf(x))); } } else { Entry<K,V> y = leftOf(parentOf(parentOf(x))); if (colorOf(y) == RED) { setColor(parentOf(x), BLACK); setColor(y, BLACK); setColor(parentOf(parentOf(x)), RED); x = parentOf(parentOf(x)); } else { if (x == leftOf(parentOf(x))) { x = parentOf(x); rotateRight(x); } setColor(parentOf(x), BLACK); setColor(parentOf(parentOf(x)), RED); rotateLeft(parentOf(parentOf(x))); } } } root.color = BLACK; } // 刪除“紅黑樹的節點p” private void deleteEntry(Entry<K,V> p) { modCount++; size--; // If strictly internal, copy successor's element to p and then make p // point to successor. if (p.left != null && p.right != null) { Entry<K,V> s = successor (p); p.key = s.key; p.value = s.value; p = s; } // p has 2 children // Start fixup at replacement node, if it exists. Entry<K,V> replacement = (p.left != null ? p.left : p.right); if (replacement != null) { // Link replacement to parent replacement.parent = p.parent; if (p.parent == null) root = replacement; else if (p == p.parent.left) p.parent.left = replacement; else p.parent.right = replacement; // Null out links so they are OK to use by fixAfterDeletion. p.left = p.right = p.parent = null; // Fix replacement if (p.color == BLACK) fixAfterDeletion(replacement); } else if (p.parent == null) { // return if we are the only node. root = null; } else { // No children. Use self as phantom replacement and unlink. if (p.color == BLACK) fixAfterDeletion(p); if (p.parent != null) { if (p == p.parent.left) p.parent.left = null; else if (p == p.parent.right) p.parent.right = null; p.parent = null; } } } // 刪除之後的修正操作。 // 目的是保證:紅黑樹刪除節點之後,仍然是一顆紅黑樹 private void fixAfterDeletion(Entry<K,V> x) { while (x != root && colorOf(x) == BLACK) { if (x == leftOf(parentOf(x))) { Entry<K,V> sib = rightOf(parentOf(x)); if (colorOf(sib) == RED) { setColor(sib, BLACK); setColor(parentOf(x), RED); rotateLeft(parentOf(x)); sib = rightOf(parentOf(x)); } if (colorOf(leftOf(sib)) == BLACK && colorOf(rightOf(sib)) == BLACK) { setColor(sib, RED); x = parentOf(x); } else { if (colorOf(rightOf(sib)) == BLACK) { setColor(leftOf(sib), BLACK); setColor(sib, RED); rotateRight(sib); sib = rightOf(parentOf(x)); } setColor(sib, colorOf(parentOf(x))); setColor(parentOf(x), BLACK); setColor(rightOf(sib), BLACK); rotateLeft(parentOf(x)); x = root; } } else { // symmetric Entry<K,V> sib = leftOf(parentOf(x)); if (colorOf(sib) == RED) { setColor(sib, BLACK); setColor(parentOf(x), RED); rotateRight(parentOf(x)); sib = leftOf(parentOf(x)); } if (colorOf(rightOf(sib)) == BLACK && colorOf(leftOf(sib)) == BLACK) { setColor(sib, RED); x = parentOf(x); } else { if (colorOf(leftOf(sib)) == BLACK) { setColor(rightOf(sib), BLACK); setColor(sib, RED); rotateLeft(sib); sib = leftOf(parentOf(x)); } setColor(sib, colorOf(parentOf(x))); setColor(parentOf(x), BLACK); setColor(leftOf(sib), BLACK); rotateRight(parentOf(x)); x = root; } } } setColor(x, BLACK); } private static final long serialVersionUID = 919286545866124006L; // java.io.Serializable的寫入函數 // 將TreeMap的“容量,所有的Entry”都寫入到輸出流中 private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { // Write out the Comparator and any hidden stuff s.defaultWriteObject(); // Write out size (number of Mappings) s.writeInt(size); // Write out keys and values (alternating) for (Iterator<Map.Entry<K,V>> i = entrySet().iterator(); i.hasNext(); ) { Map.Entry<K,V> e = i.next(); s.writeObject(e.getKey()); s.writeObject(e.getValue()); } } // java.io.Serializable的讀取函數:根據寫入方式讀出 // 先將TreeMap的“容量、所有的Entry”依次讀出 private void readObject(final java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in the Comparator and any hidden stuff s.defaultReadObject(); // Read in size int size = s.readInt(); buildFromSorted(size, null, s, null); } // 根據已經一個排好序的map創建一個TreeMap private void buildFromSorted(int size, Iterator it, java.io.ObjectInputStream str, V defaultVal) throws java.io.IOException, ClassNotFoundException { this.size = size; root = buildFromSorted(0, 0, size-1, computeRedLevel(size), it, str, defaultVal); } // 根據已經一個排好序的map創建一個TreeMap // 將map中的元素逐個添加到TreeMap中,並返回map的中間元素作為根節點。 private final Entry<K,V> buildFromSorted(int level, int lo, int hi, int redLevel, Iterator it, java.io.ObjectInputStream str, V defaultVal) throws java.io.IOException, ClassNotFoundException { if (hi < lo) return null; // 獲取中間元素 int mid = (lo + hi) / 2; Entry<K,V> left = null; // 若lo小於mid,則遞歸調用獲取(middel的)左孩子。 if (lo < mid) left = buildFromSorted(level+1, lo, mid - 1, redLevel, it, str, defaultVal); // 獲取middle節點對應的key和value K key; V value; if (it != null) { if (defaultVal==null) { Map.Entry<K,V> entry = (Map.Entry<K,V>)it.next(); key = entry.getKey(); value = entry.getValue(); } else { key = (K)it.next(); value = defaultVal; } } else { // use stream key = (K) str.readObject(); value = (defaultVal != null ? defaultVal : (V) str.readObject()); } // 創建middle節點 Entry<K,V> middle = new Entry<K,V>(key, value, null); // 若當前節點的深度=紅色節點的深度,則將節點著色為紅色。 if (level == redLevel) middle.color = RED; // 設置middle為left的父親,left為middle的左孩子 if (left != null) { middle.left = left; left.parent = middle; } if (mid < hi) { // 遞歸調用獲取(middel的)右孩子。 Entry<K,V> right = buildFromSorted(level+1, mid+1, hi, redLevel, it, str, defaultVal); // 設置middle為left的父親,left為middle的左孩子 middle.right = right; right.parent = middle; } return middle; } // 計算節點樹為sz的最大深度,也是紅色節點的深度值。 private static int computeRedLevel(int sz) { int level = 0; for (int m = sz - 1; m >= 0; m = m / 2 - 1) level++; return level; } }
說明:
在詳細介紹TreeMap的代碼之前,我們先建立一個整體概念。
TreeMap是通過紅黑樹實現的,TreeMap存儲的是key-value鍵值對,TreeMap的排序是基於對key的排序。
TreeMap提供了操作“key”、“key-value”、“value”等方法,也提供了對TreeMap這顆樹進行整體操作的方法,如獲取子樹、反向樹。
後面的解說內容分為幾部分,
首先,介紹TreeMap的核心,即紅黑樹相關部分;
然後,介紹TreeMap的主要函數;
再次,介紹TreeMap實現的幾個接口;
最後,補充介紹TreeMap的其它內容。
TreeMap本質上是一顆紅黑樹。要徹底理解TreeMap,建議讀者先理解紅黑樹。關於紅黑樹的原理,可以參考:紅黑樹(一) 原理和算法詳細介紹
第2.1部分 TreeMap的紅黑樹相關內容
TreeMap中於紅黑樹相關的主要函數有:
1 數據結構
1.1 紅黑樹的節點顏色--紅色
private static final boolean RED = false;
1.2 紅黑樹的節點顏色--黑色
private static final boolean BLACK = true;
1.3 “紅黑樹的節點”對應的類。
static final class Entry<K,V> implements Map.Entry<K,V> { ... }
Entry包含了6個部分內容:key(鍵)、value(值)、left(左孩子)、right(右孩子)、parent(父節點)、color(顏色)
Entry節點根據key進行排序,Entry節點包含的內容為value。
2 相關操作
2.1 左旋
private void rotateLeft(Entry<K,V> p) { ... }
2.2 右旋
private void rotateRight(Entry<K,V> p) { ... }
2.3 插入操作
public V put(K key, V value) { ... }
2.4 插入修正操作
紅黑樹執行插入操作之後,要執行“插入修正操作”。
目的是:保紅黑樹在進行插入節點之後,仍然是一顆紅黑樹
private void fixAfterInsertion(Entry<K,V> x) { ... }
2.5 刪除操作
private void deleteEntry(Entry<K,V> p) { ... }
2.6 刪除修正操作
紅黑樹執行刪除之後,要執行“刪除修正操作”。
目的是保證:紅黑樹刪除節點之後,仍然是一顆紅黑樹
private void fixAfterDeletion(Entry<K,V> x) { ... }
關於紅黑樹部分,這裡主要是指出了TreeMap中那些是紅黑樹的主要相關內容。具體的紅黑樹相關操作API,這裡沒有詳細說明,因為它們僅僅只是將算法翻譯成代碼。讀者可以參考“紅黑樹(一) 原理和算法詳細介紹”進行了解。
第2.2部分 TreeMap的構造函數
1 默認構造函數
使用默認構造函數構造TreeMap時,使用java的默認的比較器比較Key的大小,從而對TreeMap進行排序。
public TreeMap() {
comparator = null;
}
2 帶比較器的構造函數
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
3 帶Map的構造函數,Map會成為TreeMap的子集
public TreeMap(Map<? extends K, ? extends V> m) {
comparator = null;
putAll(m);
}
該構造函數會調用putAll()將m中的所有元素添加到TreeMap中。putAll()源碼如下:
public void putAll(Map<? extends K, ? extends V> m) {
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
put(e.getKey(), e.getValue());
}
從中,我們可以看出putAll()就是將m中的key-value逐個的添加到TreeMap中。
4 帶SortedMap的構造函數,SortedMap會成為TreeMap的子集
public TreeMap(SortedMap<K, ? extends V> m) { comparator = m.comparator(); try { buildFromSorted(m.size(), m.entrySet().iterator(), null, null); } catch (java.io.IOException cannotHappen) { } catch (ClassNotFoundException cannotHappen) { } }
該構造函數不同於上一個構造函數,在上一個構造函數中傳入的參數是Map,Map不是有序的,所以要逐個添加。
而該構造函數的參數是SortedMap是一個有序的Map,我們通過buildFromSorted()來創建對應的Map。
buildFromSorted涉及到的代碼如下:
// 根據已經一個排好序的map創建一個TreeMap // 將map中的元素逐個添加到TreeMap中,並返回map的中間元素作為根節點。 private final Entry<K,V> buildFromSorted(int level, int lo, int hi, int redLevel, Iterator it, java.io.ObjectInputStream str, V defaultVal) throws java.io.IOException, ClassNotFoundException { if (hi < lo) return null; // 獲取中間元素 int mid = (lo + hi) / 2; Entry<K,V> left = null; // 若lo小於mid,則遞歸調用獲取(middel的)左孩子。 if (lo < mid) left = buildFromSorted(level+1, lo, mid - 1, redLevel, it, str, defaultVal); // 獲取middle節點對應的key和value K key; V value; if (it != null) { if (defaultVal==null) { Map.Entry<K,V> entry = (Map.Entry<K,V>)it.next(); key = entry.getKey(); value = entry.getValue(); } else { key = (K)it.next(); value = defaultVal; } } else { // use stream key = (K) str.readObject(); value = (defaultVal != null ? defaultVal : (V) str.readObject()); } // 創建middle節點 Entry<K,V> middle = new Entry<K,V>(key, value, null); // 若當前節點的深度=紅色節點的深度,則將節點著色為紅色。 if (level == redLevel) middle.color = RED; // 設置middle為left的父親,left為middle的左孩子 if (left != null) { middle.left = left; left.parent = middle; } if (mid < hi) { // 遞歸調用獲取(middel的)右孩子。 Entry<K,V> right = buildFromSorted(level+1, mid+1, hi, redLevel, it, str, defaultVal); // 設置middle為left的父親,left為middle的左孩子 middle.right = right; right.parent = middle; } return middle; }
要理解buildFromSorted,重點說明以下幾點:
第一,buildFromSorted是通過遞歸將SortedMap中的元素逐個關聯。
第二,buildFromSorted返回middle節點(中間節點)作為root。
第三,buildFromSorted添加到紅黑樹中時,只將level == redLevel的節點設為紅色。第level級節點,實際上是buildFromSorted轉換成紅黑樹後的最底端(假設根節點在最上方)的節點;只將紅黑樹最底端的階段著色為紅色,其余都是黑色。
第2.3部分 TreeMap的Entry相關函數
TreeMap的 firstEntry()、 lastEntry()、 lowerEntry()、 higherEntry()、 floorEntry()、 ceilingEntry()、 pollFirstEntry() 、 pollLastEntry() 原理都是類似的;下面以firstEntry()來進行詳細說明
我們先看看firstEntry()和getFirstEntry()的代碼:
public Map.Entry<K,V> firstEntry() { return exportEntry(getFirstEntry()); } final Entry<K,V> getFirstEntry() { Entry<K,V> p = root; if (p != null) while (p.left != null) p = p.left; return p; }
從中,我們可以看出 firstEntry() 和 getFirstEntry() 都是用於獲取第一個節點。
但是,firstEntry() 是對外接口; getFirstEntry() 是內部接口。而且,firstEntry() 是通過 getFirstEntry() 來實現的。那為什麼外界不能直接調用 getFirstEntry(),而需要多此一舉的調用 firstEntry() 呢?
先告訴大家原因,再進行詳細說明。這麼做的目的是:防止用戶修改返回的Entry。getFirstEntry()返回的Entry是可以被修改的,但是經過firstEntry()返回的Entry不能被修改,只可以讀取Entry的key值和value值。下面我們看看到底是如何實現的。
(01) getFirstEntry()返回的是Entry節點,而Entry是紅黑樹的節點,它的源碼如下:
// 返回“紅黑樹的第一個節點” final Entry<K,V> getFirstEntry() { Entry<K,V> p = root; if (p != null) while (p.left != null) p = p.left; return p; }
從中,我們可以調用Entry的getKey()、getValue()來獲取key和value值,以及調用setValue()來修改value的值。
(02) firstEntry()返回的是exportEntry(getFirstEntry())。下面我們看看exportEntry()干了些什麼?
static <K,V> Map.Entry<K,V> exportEntry(TreeMap.Entry<K,V> e) {
return e == null? null :
new AbstractMap.SimpleImmutableEntry<K,V>(e);
}
實際上,exportEntry() 是新建一個AbstractMap.SimpleImmutableEntry類型的對象,並返回。
SimpleImmutableEntry的實現在AbstractMap.java中,下面我們看看AbstractMap.SimpleImmutableEntry是如何實現的,代碼如下:
public static class SimpleImmutableEntry<K,V> implements Entry<K,V>, java.io.Serializable { private static final long serialVersionUID = 7138329143949025153L; private final K key; private final V value; public SimpleImmutableEntry(K key, V value) { this.key = key; this.value = value; } public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) { this.key = entry.getKey(); this.value = entry.getValue(); } public K getKey() { return key; } public V getValue() { return value; } public V setValue(V value) { throw new UnsupportedOperationException(); } public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry e = (Map.Entry)o; return eq(key, e.getKey()) && eq(value, e.getValue()); } public int hashCode() { return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()); } public String toString() { return key + "=" + value; } }
從中,我們可以看出SimpleImmutableEntry實際上是簡化的key-value節點。
它只提供了getKey()、getValue()方法類獲取節點的值;但不能修改value的值,因為調用 setValue() 會拋出異常UnsupportedOperationException();
再回到我們之前的問題:那為什麼外界不能直接調用 getFirstEntry(),而需要多此一舉的調用 firstEntry() 呢?
現在我們清晰的了解到:
(01) firstEntry()是對外接口,而getFirstEntry()是內部接口。
(02) 對firstEntry()返回的Entry對象只能進行getKey()、getValue()等讀取操作;而對getFirstEntry()返回的對象除了可以進行讀取操作之後,還可以通過setValue()修改值。
第2.4部分 TreeMap的key相關函數
TreeMap的firstKey()、lastKey()、lowerKey()、higherKey()、floorKey()、ceilingKey()原理都是類似的;下面以ceilingKey()來進行詳細說明
ceilingKey(K key)的作用是“返回大於/等於key的最小的鍵值對所對應的KEY,沒有的話返回null”,它的代碼如下:
public K ceilingKey(K key) {
return keyOrNull(getCeilingEntry(key));
}
ceilingKey()是通過getCeilingEntry()實現的。keyOrNull()的代碼很簡單,它是獲取節點的key,沒有的話,返回null。
static <K,V> K keyOrNull(TreeMap.Entry<K,V> e) {
return e == null? null : e.key;
}
getCeilingEntry(K key)的作用是“獲取TreeMap中大於/等於key的最小的節點,若不存在(即TreeMap中所有節點的鍵都比key大),就返回null”。它的實現代碼如下:
final Entry<K,V> getCeilingEntry(K key) { Entry<K,V> p = root; while (p != null) { int cmp = compare(key, p.key); // 情況一:若“p的key” > key。 // 若 p 存在左孩子,則設 p=“p的左孩子”; // 否則,返回p if (cmp < 0) { if (p.left != null) p = p.left; else return p; // 情況二:若“p的key” < key。 } else if (cmp > 0) { // 若 p 存在右孩子,則設 p=“p的右孩子” if (p.right != null) { p = p.right; } else { // 若 p 不存在右孩子,則找出 p 的後繼節點,並返回 // 注意:這裡返回的 “p的後繼節點”有2種可能性:第一,null;第二,TreeMap中大於key的最小的節點。 // 理解這一點的核心是,getCeilingEntry是從root開始遍歷的。 // 若getCeilingEntry能走到這一步,那麼,它之前“已經遍歷過的節點的key”都 > key。 // 能理解上面所說的,那麼就很容易明白,為什麼“p的後繼節點”有2種可能性了。 Entry<K,V> parent = p.parent; Entry<K,V> ch = p; while (parent != null && ch == parent.right) { ch = parent; parent = parent.parent; } return parent; } // 情況三:若“p的key” = key。 } else return p; } return null; }
第2.5部分 TreeMap的values()函數
values() 返回“TreeMap中值的集合”
values()的實現代碼如下:
public Collection<V> values() {
Collection<V> vs = values;
return (vs != null) ? vs : (values = new Values());
}
說明:從中,我們可以發現values()是通過 new Values() 來實現 “返回TreeMap中值的集合”。
那麼Values()是如何實現的呢? 沒錯!由於返回的是值的集合,那麼Values()肯定返回一個集合;而Values()正好是集合類Value的構造函數。Values繼承於AbstractCollection,它的代碼如下:
// ”TreeMap的值的集合“對應的類,它集成於AbstractCollection class Values extends AbstractCollection<V> { // 返回迭代器 public Iterator<V> iterator() { return new ValueIterator(getFirstEntry()); } // 返回個數 public int size() { return TreeMap.this.size(); } // "TreeMap的值的集合"中是否包含"對象o" public boolean contains(Object o) { return TreeMap.this.containsValue(o); } // 刪除"TreeMap的值的集合"中的"對象o" public boolean remove(Object o) { for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e)) { if (valEquals(e.getValue(), o)) { deleteEntry(e); return true; } } return false; } // 清空刪除"TreeMap的值的集合" public void clear() { TreeMap.this.clear(); } }
說明:從中,我們可以知道Values類就是一個集合。而 AbstractCollection 實現了除 size() 和 iterator() 之外的其它函數,因此只需要在Values類中實現這兩個函數即可。
size() 的實現非常簡單,Values集合中元素的個數=該TreeMap的元素個數。(TreeMap每一個元素都有一個值嘛!)
iterator() 則返回一個迭代器,用於遍歷Values。下面,我們一起可以看看iterator()的實現:
public Iterator<V> iterator() {
return new ValueIterator(getFirstEntry());
}
說明: iterator() 是通過ValueIterator() 返回迭代器的,ValueIterator是一個類。代碼如下:
final class ValueIterator extends PrivateEntryIterator<V> { ValueIterator(Entry<K,V> first) { super(first); } public V next() { return nextEntry().value; } }
查看本欄目
說明:ValueIterator的代碼很簡單,它的主要實現應該在它的父類PrivateEntryIterator中。下面我們一起看看PrivateEntryIterator的代碼:
abstract class PrivateEntryIterator<T> implements Iterator<T> { // 下一節點 Entry<K,V> next; // 上一次返回的節點 Entry<K,V> lastReturned; // 修改次數統計數 int expectedModCount; PrivateEntryIterator(Entry<K,V> first) { expectedModCount = modCount; lastReturned = null; next = first; } // 是否存在下一個節點 public final boolean hasNext() { return next != null; } // 返回下一個節點 final Entry<K,V> nextEntry() { Entry<K,V> e = next; if (e == null) throw new NoSuchElementException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); next = successor(e); lastReturned = e; return e; } // 返回上一節點 final Entry<K,V> prevEntry() { Entry<K,V> e = next; if (e == null) throw new NoSuchElementException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); next = predecessor(e); lastReturned = e; return e; } // 刪除當前節點 public void remove() { if (lastReturned == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); // deleted entries are replaced by their successors if (lastReturned.left != null && lastReturned.right != null) next = lastReturned; deleteEntry(lastReturned); expectedModCount = modCount; lastReturned = null; } }
說明:PrivateEntryIterator是一個抽象類,它的實現很簡單,只只實現了Iterator的remove()和hasNext()接口,沒有實現next()接口。
而我們在ValueIterator中已經實現的next()接口。
至此,我們就了解了iterator()的完整實現了。
第2.6部分 TreeMap的entrySet()函數
entrySet() 返回“鍵值對集合”。顧名思義,它返回的是一個集合,集合的元素是“鍵值對”。
下面,我們看看它是如何實現的?entrySet() 的實現代碼如下:
public Set<Map.Entry<K,V>> entrySet() {
EntrySet es = entrySet;
return (es != null) ? es : (entrySet = new EntrySet());
}
說明:entrySet()返回的是一個EntrySet對象。
下面我們看看EntrySet的代碼:
// EntrySet是“TreeMap的所有鍵值對組成的集合”, // EntrySet集合的單位是單個“鍵值對”。 class EntrySet extends AbstractSet<Map.Entry<K,V>> { public Iterator<Map.Entry<K,V>> iterator() { return new EntryIterator(getFirstEntry()); } // EntrySet中是否包含“鍵值對Object” public boolean contains(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<K,V> entry = (Map.Entry<K,V>) o; V value = entry.getValue(); Entry<K,V> p = getEntry(entry.getKey()); return p != null && valEquals(p.getValue(), value); } // 刪除EntrySet中的“鍵值對Object” public boolean remove(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<K,V> entry = (Map.Entry<K,V>) o; V value = entry.getValue(); Entry<K,V> p = getEntry(entry.getKey()); if (p != null && valEquals(p.getValue(), value)) { deleteEntry(p); return true; } return false; } // 返回EntrySet中元素個數 public int size() { return TreeMap.this.size(); } // 清空EntrySet public void clear() { TreeMap.this.clear(); } }
說明:
EntrySet是“TreeMap的所有鍵值對組成的集合”,而且它單位是單個“鍵值對”。
EntrySet是一個集合,它繼承於AbstractSet。而AbstractSet實現了除size() 和 iterator() 之外的其它函數,因此,我們重點了解一下EntrySet的size() 和 iterator() 函數
size() 的實現非常簡單,AbstractSet集合中元素的個數=該TreeMap的元素個數。
iterator() 則返回一個迭代器,用於遍歷AbstractSet。從上面的源碼中,我們可以發現iterator() 是通過EntryIterator實現的;下面我們看看EntryIterator的源碼:
final class EntryIterator extends PrivateEntryIterator<Map.Entry<K,V>> { EntryIterator(Entry<K,V> first) { super(first); } public Map.Entry<K,V> next() { return nextEntry(); } }
說明:和Values類一樣,EntryIterator也繼承於PrivateEntryIterator類。
第2.7部分 TreeMap實現的Cloneable接口
TreeMap實現了Cloneable接口,即實現了clone()方法。
clone()方法的作用很簡單,就是克隆一個TreeMap對象並返回。
// 克隆一個TreeMap,並返回Object對象 public Object clone() { TreeMap<K,V> clone = null; try { clone = (TreeMap<K,V>) super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); } // Put clone into "virgin" state (except for comparator) clone.root = null; clone.size = 0; clone.modCount = 0; clone.entrySet = null; clone.navigableKeySet = null; clone.descendingMap = null; // Initialize clone with our mappings try { clone.buildFromSorted(size, entrySet().iterator(), null, null); } catch (java.io.IOException cannotHappen) { } catch (ClassNotFoundException cannotHappen) { } return clone; }
第2.8部分 TreeMap實現的Serializable接口
TreeMap實現java.io.Serializable,分別實現了串行讀取、寫入功能。
串行寫入函數是writeObject(),它的作用是將TreeMap的“容量,所有的Entry”都寫入到輸出流中。
而串行讀取函數是readObject(),它的作用是將TreeMap的“容量、所有的Entry”依次讀出。
readObject() 和 writeObject() 正好是一對,通過它們,我能實現TreeMap的串行傳輸。
// java.io.Serializable的寫入函數 // 將TreeMap的“容量,所有的Entry”都寫入到輸出流中 private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { // Write out the Comparator and any hidden stuff s.defaultWriteObject(); // Write out size (number of Mappings) s.writeInt(size); // Write out keys and values (alternating) for (Iterator<Map.Entry<K,V>> i = entrySet().iterator(); i.hasNext(); ) { Map.Entry<K,V> e = i.next(); s.writeObject(e.getKey()); s.writeObject(e.getValue()); } } // java.io.Serializable的讀取函數:根據寫入方式讀出 // 先將TreeMap的“容量、所有的Entry”依次讀出 private void readObject(final java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in the Comparator and any hidden stuff s.defaultReadObject(); // Read in size int size = s.readInt(); buildFromSorted(size, null, s, null); }
說到這裡,就順便說一下“關鍵字transient”的作用
transient是Java語言的關鍵字,它被用來表示一個域不是該對象串行化的一部分。
Java的serialization提供了一種持久化對象實例的機制。當持久化對象時,可能有一個特殊的對象數據成員,我們不想用serialization機制來保存它。為了在一個特定對象的一個域上關閉serialization,可以在這個域前加上關鍵字transient。
當一個對象被串行化的時候,transient型變量的值不包括在串行化的表示中,然而非transient型的變量是被包括進去的。
第2.9部分 TreeMap實現的NavigableMap接口
firstKey()、lastKey()、lowerKey()、higherKey()、ceilingKey()、floorKey();
firstEntry()、 lastEntry()、 lowerEntry()、 higherEntry()、 floorEntry()、 ceilingEntry()、 pollFirstEntry() 、 pollLastEntry();
上面已經講解過這些API了,下面對其它的API進行說明。
1 反向TreeMap
descendingMap() 的作用是返回當前TreeMap的反向的TreeMap。所謂反向,就是排序順序和原始的順序相反。
我們已經知道TreeMap是一顆紅黑樹,而紅黑樹是有序的。
TreeMap的排序方式是通過比較器,在創建TreeMap的時候,若指定了比較器,則使用該比較器;否則,就使用Java的默認比較器。
而獲取TreeMap的反向TreeMap的原理就是將比較器反向即可!
理解了descendingMap()的反向原理之後,再講解一下descendingMap()的代碼。
// 獲取TreeMap的降序Map public NavigableMap<K, V> descendingMap() { NavigableMap<K, V> km = descendingMap; return (km != null) ? km : (descendingMap = new DescendingSubMap(this, true, null, true, true, null, true)); }
從中,我們看出descendingMap()實際上是返回DescendingSubMap類的對象。下面,看看DescendingSubMap的源碼:
static final class DescendingSubMap<K,V> extends NavigableSubMap<K,V> { private static final long serialVersionUID = 912986545866120460L; DescendingSubMap(TreeMap<K,V> m, boolean fromStart, K lo, boolean loInclusive, boolean toEnd, K hi, boolean hiInclusive) { super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive); } // 反轉的比較器:是將原始比較器反轉得到的。 private final Comparator<? super K> reverseComparator = Collections.reverseOrder(m.comparator); // 獲取反轉比較器 public Comparator<? super K> comparator() { return reverseComparator; } // 獲取“子Map”。 // 范圍是從fromKey 到 toKey;fromInclusive是是否包含fromKey的標記,toInclusive是是否包含toKey的標記 public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { if (!inRange(fromKey, fromInclusive)) throw new IllegalArgumentException("fromKey out of range"); if (!inRange(toKey, toInclusive)) throw new IllegalArgumentException("toKey out of range"); return new DescendingSubMap(m, false, toKey, toInclusive, false, fromKey, fromInclusive); } // 獲取“Map的頭部”。 // 范圍從第一個節點 到 toKey, inclusive是是否包含toKey的標記 public NavigableMap<K,V> headMap(K toKey, boolean inclusive) { if (!inRange(toKey, inclusive)) throw new IllegalArgumentException("toKey out of range"); return new DescendingSubMap(m, false, toKey, inclusive, toEnd, hi, hiInclusive); } // 獲取“Map的尾部”。 // 范圍是從 fromKey 到 最後一個節點,inclusive是是否包含fromKey的標記 public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive){ if (!inRange(fromKey, inclusive)) throw new IllegalArgumentException("fromKey out of range"); return new DescendingSubMap(m, fromStart, lo, loInclusive, false, fromKey, inclusive); } // 獲取對應的降序Map public NavigableMap<K,V> descendingMap() { NavigableMap<K,V> mv = descendingMapView; return (mv != null) ? mv : (descendingMapView = new AscendingSubMap(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive)); } // 返回“升序Key迭代器” Iterator<K> keyIterator() { return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); } // 返回“降序Key迭代器” Iterator<K> descendingKeyIterator() { return new SubMapKeyIterator(absLowest(), absHighFence()); } // “降序EntrySet集合”類 // 實現了iterator() final class DescendingEntrySetView extends EntrySetView { public Iterator<Map.Entry<K,V>> iterator() { return new DescendingSubMapEntryIterator(absHighest(), absLowFence()); } } // 返回“降序EntrySet集合” public Set<Map.Entry<K,V>> entrySet() { EntrySetView es = entrySetView; return (es != null) ? es : new DescendingEntrySetView(); } TreeMap.Entry<K,V> subLowest() { return absHighest(); } TreeMap.Entry<K,V> subHighest() { return absLowest(); } TreeMap.Entry<K,V> subCeiling(K key) { return absFloor(key); } TreeMap.Entry<K,V> subHigher(K key) { return absLower(key); } TreeMap.Entry<K,V> subFloor(K key) { return absCeiling(key); } TreeMap.Entry<K,V> subLower(K key) { return absHigher(key); } }
從中,我們看出DescendingSubMap是降序的SubMap,它的實現機制是將“SubMap的比較器反轉”。
它繼承於NavigableSubMap。而NavigableSubMap是一個繼承於AbstractMap的抽象類;它包括2個子類——"(升序)AscendingSubMap"和"(降序)DescendingSubMap"。NavigableSubMap為它的兩個子類實現了許多公共API。
下面看看NavigableSubMap的源碼。
static abstract class NavigableSubMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, java.io.Serializable { // TreeMap的拷貝 final TreeMap<K,V> m; // lo是“子Map范圍的最小值”,hi是“子Map范圍的最大值”; // loInclusive是“是否包含lo的標記”,hiInclusive是“是否包含hi的標記” // fromStart是“表示是否從第一個節點開始計算”, // toEnd是“表示是否計算到最後一個節點 ” final K lo, hi; final boolean fromStart, toEnd; final boolean loInclusive, hiInclusive; // 構造函數 NavigableSubMap(TreeMap<K,V> m, boolean fromStart, K lo, boolean loInclusive, boolean toEnd, K hi, boolean hiInclusive) { if (!fromStart && !toEnd) { if (m.compare(lo, hi) > 0) throw new IllegalArgumentException("fromKey > toKey"); } else { if (!fromStart) // type check m.compare(lo, lo); if (!toEnd) m.compare(hi, hi); } this.m = m; this.fromStart = fromStart; this.lo = lo; this.loInclusive = loInclusive; this.toEnd = toEnd; this.hi = hi; this.hiInclusive = hiInclusive; } // 判斷key是否太小 final boolean tooLow(Object key) { // 若該SubMap不包括“起始節點”, // 並且,“key小於最小鍵(lo)”或者“key等於最小鍵(lo),但最小鍵卻沒包括在該SubMap內” // 則判斷key太小。其余情況都不是太小! if (!fromStart) { int c = m.compare(key, lo); if (c < 0 || (c == 0 && !loInclusive)) return true; } return false; } // 判斷key是否太大 final boolean tooHigh(Object key) { // 若該SubMap不包括“結束節點”, // 並且,“key大於最大鍵(hi)”或者“key等於最大鍵(hi),但最大鍵卻沒包括在該SubMap內” // 則判斷key太大。其余情況都不是太大! if (!toEnd) { int c = m.compare(key, hi); if (c > 0 || (c == 0 && !hiInclusive)) return true; } return false; } // 判斷key是否在“lo和hi”開區間范圍內 final boolean inRange(Object key) { return !tooLow(key) && !tooHigh(key); } // 判斷key是否在封閉區間內 final boolean inClosedRange(Object key) { return (fromStart || m.compare(key, lo) >= 0) && (toEnd || m.compare(hi, key) >= 0); } // 判斷key是否在區間內, inclusive是區間開關標志 final boolean inRange(Object key, boolean inclusive) { return inclusive ? inRange(key) : inClosedRange(key); } // 返回最低的Entry final TreeMap.Entry<K,V> absLowest() { // 若“包含起始節點”,則調用getFirstEntry()返回第一個節點 // 否則的話,若包括lo,則調用getCeilingEntry(lo)獲取大於/等於lo的最小的Entry; // 否則,調用getHigherEntry(lo)獲取大於lo的最小Entry TreeMap.Entry<K,V> e = (fromStart ? m.getFirstEntry() : (loInclusive ? m.getCeilingEntry(lo) : m.getHigherEntry(lo))); return (e == null || tooHigh(e.key)) ? null : e; } // 返回最高的Entry final TreeMap.Entry<K,V> absHighest() { // 若“包含結束節點”,則調用getLastEntry()返回最後一個節點 // 否則的話,若包括hi,則調用getFloorEntry(hi)獲取小於/等於hi的最大的Entry; // 否則,調用getLowerEntry(hi)獲取大於hi的最大Entry TreeMap.Entry<K,V> e = TreeMap.Entry<K,V> e = (toEnd ? m.getLastEntry() : (hiInclusive ? m.getFloorEntry(hi) : m.getLowerEntry(hi))); return (e == null || tooLow(e.key)) ? null : e; } // 返回"大於/等於key的最小的Entry" final TreeMap.Entry<K,V> absCeiling(K key) { // 只有在“key太小”的情況下,absLowest()返回的Entry才是“大於/等於key的最小Entry” // 其它情況下不行。例如,當包含“起始節點”時,absLowest()返回的是最小Entry了! if (tooLow(key)) return absLowest(); // 獲取“大於/等於key的最小Entry” TreeMap.Entry<K,V> e = m.getCeilingEntry(key); return (e == null || tooHigh(e.key)) ? null : e; } // 返回"大於key的最小的Entry" final TreeMap.Entry<K,V> absHigher(K key) { // 只有在“key太小”的情況下,absLowest()返回的Entry才是“大於key的最小Entry” // 其它情況下不行。例如,當包含“起始節點”時,absLowest()返回的是最小Entry了,而不一定是“大於key的最小Entry”! if (tooLow(key)) return absLowest(); // 獲取“大於key的最小Entry” TreeMap.Entry<K,V> e = m.getHigherEntry(key); return (e == null || tooHigh(e.key)) ? null : e; } // 返回"小於/等於key的最大的Entry" final TreeMap.Entry<K,V> absFloor(K key) { // 只有在“key太大”的情況下,(absHighest)返回的Entry才是“小於/等於key的最大Entry” // 其它情況下不行。例如,當包含“結束節點”時,absHighest()返回的是最大Entry了! if (tooHigh(key)) return absHighest(); // 獲取"小於/等於key的最大的Entry" TreeMap.Entry<K,V> e = m.getFloorEntry(key); return (e == null || tooLow(e.key)) ? null : e; } // 返回"小於key的最大的Entry" final TreeMap.Entry<K,V> absLower(K key) { // 只有在“key太大”的情況下,(absHighest)返回的Entry才是“小於key的最大Entry” // 其它情況下不行。例如,當包含“結束節點”時,absHighest()返回的是最大Entry了,而不一定是“小於key的最大Entry”! if (tooHigh(key)) return absHighest(); // 獲取"小於key的最大的Entry" TreeMap.Entry<K,V> e = m.getLowerEntry(key); return (e == null || tooLow(e.key)) ? null : e; } // 返回“大於最大節點中的最小節點”,不存在的話,返回null final TreeMap.Entry<K,V> absHighFence() { return (toEnd ? null : (hiInclusive ? m.getHigherEntry(hi) : m.getCeilingEntry(hi))); } // 返回“小於最小節點中的最大節點”,不存在的話,返回null final TreeMap.Entry<K,V> absLowFence() { return (fromStart ? null : (loInclusive ? m.getLowerEntry(lo) : m.getFloorEntry(lo))); } // 下面幾個abstract方法是需要NavigableSubMap的實現類實現的方法 abstract TreeMap.Entry<K,V> subLowest(); abstract TreeMap.Entry<K,V> subHighest(); abstract TreeMap.Entry<K,V> subCeiling(K key); abstract TreeMap.Entry<K,V> subHigher(K key); abstract TreeMap.Entry<K,V> subFloor(K key); abstract TreeMap.Entry<K,V> subLower(K key); // 返回“順序”的鍵迭代器 abstract Iterator<K> keyIterator(); // 返回“逆序”的鍵迭代器 abstract Iterator<K> descendingKeyIterator(); // 返回SubMap是否為空。空的話,返回true,否則返回false public boolean isEmpty() { return (fromStart && toEnd) ? m.isEmpty() : entrySet().isEmpty(); } // 返回SubMap的大小 public int size() { return (fromStart && toEnd) ? m.size() : entrySet().size(); } // 返回SubMap是否包含鍵key public final boolean containsKey(Object key) { return inRange(key) && m.containsKey(key); } // 將key-value 插入SubMap中 public final V put(K key, V value) { if (!inRange(key)) throw new IllegalArgumentException("key out of range"); return m.put(key, value); } // 獲取key對應值 public final V get(Object key) { return !inRange(key)? null : m.get(key); } // 刪除key對應的鍵值對 public final V remove(Object key) { return !inRange(key)? null : m.remove(key); } // 獲取“大於/等於key的最小鍵值對” public final Map.Entry<K,V> ceilingEntry(K key) { return exportEntry(subCeiling(key)); } // 獲取“大於/等於key的最小鍵” public final K ceilingKey(K key) { return keyOrNull(subCeiling(key)); } // 獲取“大於key的最小鍵值對” public final Map.Entry<K,V> higherEntry(K key) { return exportEntry(subHigher(key)); } // 獲取“大於key的最小鍵” public final K higherKey(K key) { return keyOrNull(subHigher(key)); } // 獲取“小於/等於key的最大鍵值對” public final Map.Entry<K,V> floorEntry(K key) { return exportEntry(subFloor(key)); } // 獲取“小於/等於key的最大鍵” public final K floorKey(K key) { return keyOrNull(subFloor(key)); } // 獲取“小於key的最大鍵值對” public final Map.Entry<K,V> lowerEntry(K key) { return exportEntry(subLower(key)); } // 獲取“小於key的最大鍵” public final K lowerKey(K key) { return keyOrNull(subLower(key)); } // 獲取"SubMap的第一個鍵" public final K firstKey() { return key(subLowest()); } // 獲取"SubMap的最後一個鍵" public final K lastKey() { return key(subHighest()); } // 獲取"SubMap的第一個鍵值對" public final Map.Entry<K,V> firstEntry() { return exportEntry(subLowest()); } // 獲取"SubMap的最後一個鍵值對" public final Map.Entry<K,V> lastEntry() { return exportEntry(subHighest()); } // 返回"SubMap的第一個鍵值對",並從SubMap中刪除改鍵值對 public final Map.Entry<K,V> pollFirstEntry() { TreeMap.Entry<K,V> e = subLowest(); Map.Entry<K,V> result = exportEntry(e); if (e != null) m.deleteEntry(e); return result; } // 返回"SubMap的最後一個鍵值對",並從SubMap中刪除改鍵值對 public final Map.Entry<K,V> pollLastEntry() { TreeMap.Entry<K,V> e = subHighest(); Map.Entry<K,V> result = exportEntry(e); if (e != null) m.deleteEntry(e); return result; } // Views transient NavigableMap<K,V> descendingMapView = null; transient EntrySetView entrySetView = null; transient KeySet<K> navigableKeySetView = null; // 返回NavigableSet對象,實際上返回的是當前對象的"Key集合"。 public final NavigableSet<K> navigableKeySet() { KeySet<K> nksv = navigableKeySetView; return (nksv != null) ? nksv : (navigableKeySetView = new TreeMap.KeySet(this)); } // 返回"Key集合"對象 public final Set<K> keySet() { return navigableKeySet(); } // 返回“逆序”的Key集合 public NavigableSet<K> descendingKeySet() { return descendingMap().navigableKeySet(); } // 排列fromKey(包含) 到 toKey(不包含) 的子map public final SortedMap<K,V> subMap(K fromKey, K toKey) { return subMap(fromKey, true, toKey, false); } // 返回當前Map的頭部(從第一個節點 到 toKey, 不包括toKey) public final SortedMap<K,V> headMap(K toKey) { return headMap(toKey, false); } // 返回當前Map的尾部[從 fromKey(包括fromKeyKey) 到 最後一個節點] public final SortedMap<K,V> tailMap(K fromKey) { return tailMap(fromKey, true); } // Map的Entry的集合 abstract class EntrySetView extends AbstractSet<Map.Entry<K,V>> { private transient int size = -1, sizeModCount; // 獲取EntrySet的大小 public int size() { // 若SubMap是從“開始節點”到“結尾節點”,則SubMap大小就是原TreeMap的大小 if (fromStart && toEnd) return m.size(); // 若SubMap不是從“開始節點”到“結尾節點”,則調用iterator()遍歷EntrySetView中的元素 if (size == -1 || sizeModCount != m.modCount) { sizeModCount = m.modCount; size = 0; Iterator i = iterator(); while (i.hasNext()) { size++; i.next(); } } return size; } // 判斷EntrySetView是否為空 public boolean isEmpty() { TreeMap.Entry<K,V> n = absLowest(); return n == null || tooHigh(n.key); } // 判斷EntrySetView是否包含Object public boolean contains(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<K,V> entry = (Map.Entry<K,V>) o; K key = entry.getKey(); if (!inRange(key)) return false; TreeMap.Entry node = m.getEntry(key); return node != null && valEquals(node.getValue(), entry.getValue()); } // 從EntrySetView中刪除Object public boolean remove(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<K,V> entry = (Map.Entry<K,V>) o; K key = entry.getKey(); if (!inRange(key)) return false; TreeMap.Entry<K,V> node = m.getEntry(key); if (node!=null && valEquals(node.getValue(),entry.getValue())){ m.deleteEntry(node); return true; } return false; } } // SubMap的迭代器 abstract class SubMapIterator<T> implements Iterator<T> { // 上一次被返回的Entry TreeMap.Entry<K,V> lastReturned; // 指向下一個Entry TreeMap.Entry<K,V> next; // “柵欄key”。根據SubMap是“升序”還是“降序”具有不同的意義 final K fenceKey; int expectedModCount; // 構造函數 SubMapIterator(TreeMap.Entry<K,V> first, TreeMap.Entry<K,V> fence) { // 每創建一個SubMapIterator時,保存修改次數 // 若後面發現expectedModCount和modCount不相等,則拋出ConcurrentModificationException異常。 // 這就是所說的fast-fail機制的原理! expectedModCount = m.modCount; lastReturned = null; next = first; fenceKey = fence == null ? null : fence.key; } // 是否存在下一個Entry public final boolean hasNext() { return next != null && next.key != fenceKey; } // 返回下一個Entry final TreeMap.Entry<K,V> nextEntry() { TreeMap.Entry<K,V> e = next; if (e == null || e.key == fenceKey) throw new NoSuchElementException(); if (m.modCount != expectedModCount) throw new ConcurrentModificationException(); // next指向e的後繼節點 next = successor(e); lastReturned = e; return e; } // 返回上一個Entry final TreeMap.Entry<K,V> prevEntry() { TreeMap.Entry<K,V> e = next; if (e == null || e.key == fenceKey) throw new NoSuchElementException(); if (m.modCount != expectedModCount) throw new ConcurrentModificationException(); // next指向e的前繼節點 next = predecessor(e); lastReturned = e; return e; } // 刪除當前節點(用於“升序的SubMap”)。 // 刪除之後,可以繼續升序遍歷;紅黑樹特性沒變。 final void removeAscending() { if (lastReturned == null) throw new IllegalStateException(); if (m.modCount != expectedModCount) throw new ConcurrentModificationException(); // 這裡重點強調一下“為什麼當lastReturned的左右孩子都不為空時,要將其賦值給next”。 // 目的是為了“刪除lastReturned節點之後,next節點指向的仍然是下一個節點”。 // 根據“紅黑樹”的特性可知: // 當被刪除節點有兩個兒子時。那麼,首先把“它的後繼節點的內容”復制給“該節點的內容”;之後,刪除“它的後繼節點”。 // 這意味著“當被刪除節點有兩個兒子時,刪除當前節點之後,'新的當前節點'實際上是‘原有的後繼節點(即下一個節點)’”。 // 而此時next仍然指向"新的當前節點"。也就是說next是仍然是指向下一個節點;能繼續遍歷紅黑樹。 if (lastReturned.left != null && lastReturned.right != null) next = lastReturned; m.deleteEntry(lastReturned); lastReturned = null; expectedModCount = m.modCount; } // 刪除當前節點(用於“降序的SubMap”)。 // 刪除之後,可以繼續降序遍歷;紅黑樹特性沒變。 final void removeDescending() { if (lastReturned == null) throw new IllegalStateException(); if (m.modCount != expectedModCount) throw new ConcurrentModificationException(); m.deleteEntry(lastReturned); lastReturned = null; expectedModCount = m.modCount; } } // SubMap的Entry迭代器,它只支持升序操作,繼承於SubMapIterator final class SubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> { SubMapEntryIterator(TreeMap.Entry<K,V> first, TreeMap.Entry<K,V> fence) { super(first, fence); } // 獲取下一個節點(升序) public Map.Entry<K,V> next() { return nextEntry(); } // 刪除當前節點(升序) public void remove() { removeAscending(); } } // SubMap的Key迭代器,它只支持升序操作,繼承於SubMapIterator final class SubMapKeyIterator extends SubMapIterator<K> { SubMapKeyIterator(TreeMap.Entry<K,V> first, TreeMap.Entry<K,V> fence) { super(first, fence); } // 獲取下一個節點(升序) public K next() { return nextEntry().key; } // 刪除當前節點(升序) public void remove() { removeAscending(); } } // 降序SubMap的Entry迭代器,它只支持降序操作,繼承於SubMapIterator final class DescendingSubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> { DescendingSubMapEntryIterator(TreeMap.Entry<K,V> last, TreeMap.Entry<K,V> fence) { super(last, fence); } // 獲取下一個節點(降序) public Map.Entry<K,V> next() { return prevEntry(); } // 刪除當前節點(降序) public void remove() { removeDescending(); } } // 降序SubMap的Key迭代器,它只支持降序操作,繼承於SubMapIterator final class DescendingSubMapKeyIterator extends SubMapIterator<K> { DescendingSubMapKeyIterator(TreeMap.Entry<K,V> last, TreeMap.Entry<K,V> fence) { super(last, fence); } // 獲取下一個節點(降序) public K next() { return prevEntry().key; } // 刪除當前節點(降序) public void remove() { removeDescending(); } } }
NavigableSubMap源碼很多,但不難理解;讀者可以通過源碼和注釋進行理解。
其實,讀完NavigableSubMap的源碼後,我們可以得出它的核心思想是:它是一個抽象集合類,為2個子類——"(升序)AscendingSubMap"和"(降序)DescendingSubMap"而服務;因為NavigableSubMap實現了許多公共API。它的最終目的是實現下面的一系列函數:
headMap(K toKey, boolean inclusive) headMap(K toKey) subMap(K fromKey, K toKey) subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) tailMap(K fromKey) tailMap(K fromKey, boolean inclusive) navigableKeySet() descendingKeySet()
第2.10部分 TreeMap其它函數
1 順序遍歷和逆序遍歷
TreeMap的順序遍歷和逆序遍歷原理非常簡單。
由於TreeMap中的元素是從小到大的順序排列的。因此,順序遍歷,就是從第一個元素開始,逐個向後遍歷;而倒序遍歷則恰恰相反,它是從最後一個元素開始,逐個往前遍歷。
我們可以通過 keyIterator() 和 descendingKeyIterator()來說明!
keyIterator()的作用是返回順序的KEY的集合,
descendingKeyIterator()的作用是返回逆序的KEY的集合。
keyIterator() 的代碼如下:
Iterator<K> keyIterator() {
return new KeyIterator(getFirstEntry());
}
說明:從中我們可以看出keyIterator() 是返回以“第一個節點(getFirstEntry)” 為其實元素的迭代器。
KeyIterator的代碼如下:
final class KeyIterator extends PrivateEntryIterator<K> { KeyIterator(Entry<K,V> first) { super(first); } public K next() { return nextEntry().key; } }
說明:KeyIterator繼承於PrivateEntryIterator。當我們通過next()不斷獲取下一個元素的時候,就是執行的順序遍歷了。
descendingKeyIterator()的代碼如下:
Iterator<K> descendingKeyIterator() {
return new DescendingKeyIterator(getLastEntry());
}
說明:從中我們可以看出descendingKeyIterator() 是返回以“最後一個節點(getLastEntry)” 為其實元素的迭代器。
再看看DescendingKeyIterator的代碼:
final class DescendingKeyIterator extends PrivateEntryIterator<K> { DescendingKeyIterator(Entry<K,V> first) { super(first); } public K next() { return prevEntry().key; } }
說明:DescendingKeyIterator繼承於PrivateEntryIterator。當我們通過next()不斷獲取下一個元素的時候,實際上調用的是prevEntry()獲取的上一個節點,這樣它實際上執行的是逆序遍歷了。
至此,TreeMap的相關內容就全部介紹完畢了。若有錯誤或纰漏的地方,歡迎指正!
第3部分 TreeMap遍歷方式
3.1 遍歷TreeMap的鍵值對
第一步:根據entrySet()獲取TreeMap的“鍵值對”的Set集合。
第二步:通過Iterator迭代器遍歷“第一步”得到的集合。
// 假設map是TreeMap對象 // map中的key是String類型,value是Integer類型 Integer integ = null; Iterator iter = map.entrySet().iterator(); while(iter.hasNext()) { Map.Entry entry = (Map.Entry)iter.next(); // 獲取key key = (String)entry.getKey(); // 獲取value integ = (Integer)entry.getValue(); }
3.2 遍歷TreeMap的鍵
第一步:根據keySet()獲取TreeMap的“鍵”的Set集合。
第二步:通過Iterator迭代器遍歷“第一步”得到的集合。
// 假設map是TreeMap對象 // map中的key是String類型,value是Integer類型 String key = null; Integer integ = null; Iterator iter = map.keySet().iterator(); while (iter.hasNext()) { // 獲取key key = (String)iter.next(); // 根據key,獲取value integ = (Integer)map.get(key); }
3.3 遍歷TreeMap的值
第一步:根據value()獲取TreeMap的“值”的集合。
第二步:通過Iterator迭代器遍歷“第一步”得到的集合。
// 假設map是TreeMap對象 // map中的key是String類型,value是Integer類型 Integer value = null; Collection c = map.values(); Iterator iter= c.iterator(); while (iter.hasNext()) { value = (Integer)iter.next(); }
TreeMap遍歷測試程序如下:
import java.util.Map; import java.util.Random; import java.util.Iterator; import java.util.TreeMap; import java.util.HashSet; import java.util.Map.Entry; import java.util.Collection; /* * @desc 遍歷TreeMap的測試程序。 * (01) 通過entrySet()去遍歷key、value,參考實現函數: * iteratorTreeMapByEntryset() * (02) 通過keySet()去遍歷key、value,參考實現函數: * iteratorTreeMapByKeyset() * (03) 通過values()去遍歷value,參考實現函數: * iteratorTreeMapJustValues() * * @author skywang */ public class TreeMapIteratorTest { public static void main(String[] args) { int val = 0; String key = null; Integer value = null; Random r = new Random(); TreeMap map = new TreeMap(); for (int i=0; i<12; i++) { // 隨機獲取一個[0,100)之間的數字 val = r.nextInt(100); key = String.valueOf(val); value = r.nextInt(5); // 添加到TreeMap中 map.put(key, value); System.out.println(" key:"+key+" value:"+value); } // 通過entrySet()遍歷TreeMap的key-value iteratorTreeMapByEntryset(map) ; // 通過keySet()遍歷TreeMap的key-value iteratorTreeMapByKeyset(map) ; // 單單遍歷TreeMap的value iteratorTreeMapJustValues(map); } /* * 通過entry set遍歷TreeMap * 效率高! */ private static void iteratorTreeMapByEntryset(TreeMap map) { if (map == null) return ; System.out.println("\niterator TreeMap By entryset"); String key = null; Integer integ = null; Iterator iter = map.entrySet().iterator(); while(iter.hasNext()) { Map.Entry entry = (Map.Entry)iter.next(); key = (String)entry.getKey(); integ = (Integer)entry.getValue(); System.out.println(key+" -- "+integ.intValue()); } } /* * 通過keyset來遍歷TreeMap * 效率低! */ private static void iteratorTreeMapByKeyset(TreeMap map) { if (map == null) return ; System.out.println("\niterator TreeMap By keyset"); String key = null; Integer integ = null; Iterator iter = map.keySet().iterator(); while (iter.hasNext()) { key = (String)iter.next(); integ = (Integer)map.get(key); System.out.println(key+" -- "+integ.intValue()); } } /* * 遍歷TreeMap的values */ private static void iteratorTreeMapJustValues(TreeMap map) { if (map == null) return ; Collection c = map.values(); Iterator iter= c.iterator(); while (iter.hasNext()) { System.out.println(iter.next()); } } }
第4部分 TreeMap示例
下面通過實例來學習如何使用TreeMap
import java.util.*; /** * @desc TreeMap測試程序 * * @author skywang */ public class TreeMapTest { public static void main(String[] args) { // 測試常用的API testTreeMapOridinaryAPIs(); // 測試TreeMap的導航函數 //testNavigableMapAPIs(); // 測試TreeMap的子Map函數 //testSubMapAPIs(); } /** * 測試常用的API */ private static void testTreeMapOridinaryAPIs() { // 初始化隨機種子 Random r = new Random(); // 新建TreeMap TreeMap tmap = new TreeMap(); // 添加操作 tmap.put("one", r.nextInt(10)); tmap.put("two", r.nextInt(10)); tmap.put("three", r.nextInt(10)); System.out.printf("\n ---- testTreeMapOridinaryAPIs ----\n"); // 打印出TreeMap System.out.printf("%s\n",tmap ); // 通過Iterator遍歷key-value Iterator iter = tmap.entrySet().iterator(); while(iter.hasNext()) { Map.Entry entry = (Map.Entry)iter.next(); System.out.printf("next : %s - %s\n", entry.getKey(), entry.getValue()); } // TreeMap的鍵值對個數 System.out.printf("size: %s\n", tmap.size()); // containsKey(Object key) :是否包含鍵key System.out.printf("contains key two : %s\n",tmap.containsKey("two")); System.out.printf("contains key five : %s\n",tmap.containsKey("five")); // containsValue(Object value) :是否包含值value System.out.printf("contains value 0 : %s\n",tmap.containsValue(new Integer(0))); // remove(Object key) : 刪除鍵key對應的鍵值對 tmap.remove("three"); System.out.printf("tmap:%s\n",tmap ); // clear() : 清空TreeMap tmap.clear(); // isEmpty() : TreeMap是否為空 System.out.printf("%s\n", (tmap.isEmpty()?"tmap is empty":"tmap is not empty") ); } /** * 測試TreeMap的子Map函數 */ public static void testSubMapAPIs() { // 新建TreeMap TreeMap tmap = new TreeMap(); // 添加“鍵值對” tmap.put("a", 101); tmap.put("b", 102); tmap.put("c", 103); tmap.put("d", 104); tmap.put("e", 105); System.out.printf("\n ---- testSubMapAPIs ----\n"); // 打印出TreeMap System.out.printf("tmap:\n\t%s\n", tmap); // 測試 headMap(K toKey) System.out.printf("tmap.headMap(\"c\"):\n\t%s\n", tmap.headMap("c")); // 測試 headMap(K toKey, boolean inclusive) System.out.printf("tmap.headMap(\"c\", true):\n\t%s\n", tmap.headMap("c", true)); System.out.printf("tmap.headMap(\"c\", false):\n\t%s\n", tmap.headMap("c", false)); // 測試 tailMap(K fromKey) System.out.printf("tmap.tailMap(\"c\"):\n\t%s\n", tmap.tailMap("c")); // 測試 tailMap(K fromKey, boolean inclusive) System.out.printf("tmap.tailMap(\"c\", true):\n\t%s\n", tmap.tailMap("c", true)); System.out.printf("tmap.tailMap(\"c\", false):\n\t%s\n", tmap.tailMap("c", false)); // 測試 subMap(K fromKey, K toKey) System.out.printf("tmap.subMap(\"a\", \"c\"):\n\t%s\n", tmap.subMap("a", "c")); // 測試 System.out.printf("tmap.subMap(\"a\", true, "c", true):\n\t%s\n", tmap.subMap("a", true, "c", true)); System.out.printf("tmap.subMap(\"a\", true, "c", false):\n\t%s\n", tmap.subMap("a", true, "c", false)); System.out.printf("tmap.subMap(\"a\", false, "c", true):\n\t%s\n", tmap.subMap("a", false, "c", true)); System.out.printf("tmap.subMap(\"a\", false, "c", false):\n\t%s\n", tmap.subMap("a", false, "c", false)); // 測試 navigableKeySet() System.out.printf("tmap.navigableKeySet():\n\t%s\n", tmap.navigableKeySet()); // 測試 descendingKeySet() System.out.printf("tmap.descendingKeySet():\n\t%s\n", tmap.descendingKeySet()); } /** * 測試TreeMap的導航函數 */ public static void testNavigableMapAPIs() { // 新建TreeMap NavigableMap nav = new TreeMap(); // 添加“鍵值對” nav.put("aaa", 111); nav.put("bbb", 222); nav.put("eee", 333); nav.put("ccc", 555); nav.put("ddd", 444); System.out.printf("\n ---- testNavigableMapAPIs ----\n"); // 打印出TreeMap System.out.printf("Whole list:%s%\n", nav); // 獲取第一個key、第一個Entry System.out.printf("First key: %s\tFirst entry: %s%\n",nav.firstKey(), nav.firstEntry()); // 獲取最後一個key、最後一個Entry System.out.printf("Last key: %s\tLast entry: %s%\n",nav.lastKey(), nav.lastEntry()); // 獲取“小於/等於bbb”的最大鍵值對 System.out.printf("Key floor before bbb: %s%\n",nav.floorKey("bbb")); // 獲取“小於bbb”的最大鍵值對 System.out.printf("Key lower before bbb: %s%\n", nav.lowerKey("bbb")); // 獲取“大於/等於bbb”的最小鍵值對 System.out.printf("Key ceiling after ccc: %s%\n",nav.ceilingKey("ccc")); // 獲取“大於bbb”的最小鍵值對 System.out.printf("Key higher after ccc: %s%\n\n",nav.higherKey("ccc")); } }