1. 程式人生 > >Java 集合系列12之 TreeMap詳細介紹(原始碼解析)和使用示例

Java 集合系列12之 TreeMap詳細介紹(原始碼解析)和使用示例

   1 package java.util;
   2 
   3 public class TreeMap<K,V>
   4 extends AbstractMap<K,V>
   5 implements NavigableMap<K,V>, Cloneable, java.io.Serializable
   6 {
   7 
   8     // 比較器。用來給TreeMap排序
   9     private final Comparator<? super K> comparator;
  10 
  11     //
TreeMap是紅黑樹實現的,root是紅黑書的根節點 12 private transient Entry<K,V> root = null; 13 14 // 紅黑樹的節點總數 15 private transient int size = 0; 16 17 // 記錄紅黑樹的修改次數 18 private transient int modCount = 0; 19 20 // 預設建構函式 21 public TreeMap() { 22 comparator = null
; 23 } 24 25 // 帶比較器的建構函式 26 public TreeMap(Comparator<? super K> comparator) { 27 this.comparator = comparator; 28 } 29 30 // 帶Map的建構函式,Map會成為TreeMap的子集 31 public TreeMap(Map<? extends K, ? extends V> m) { 32 comparator = null
; 33 putAll(m); 34 } 35 36 // 帶SortedMap的建構函式,SortedMap會成為TreeMap的子集 37 public TreeMap(SortedMap<K, ? extends V> m) { 38 comparator = m.comparator(); 39 try { 40 buildFromSorted(m.size(), m.entrySet().iterator(), null, null); 41 } catch (java.io.IOException cannotHappen) { 42 } catch (ClassNotFoundException cannotHappen) { 43 } 44 } 45 46 public int size() { 47 return size; 48 } 49 50 // 返回TreeMap中是否保護“鍵(key)” 51 public boolean containsKey(Object key) { 52 return getEntry(key) != null; 53 } 54 55 // 返回TreeMap中是否保護"值(value)" 56 public boolean containsValue(Object value) { 57 // getFirstEntry() 是返回紅黑樹的第一個節點 58 // successor(e) 是獲取節點e的後繼節點 59 for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e)) 60 if (valEquals(value, e.value)) 61 return true; 62 return false; 63 } 64 65 // 獲取“鍵(key)”對應的“值(value)” 66 public V get(Object key) { 67 // 獲取“鍵”為key的節點(p) 68 Entry<K,V> p = getEntry(key); 69 // 若節點(p)為null,返回null;否則,返回節點對應的值 70 return (p==null ? null : p.value); 71 } 72 73 public Comparator<? super K> comparator() { 74 return comparator; 75 } 76 77 // 獲取第一個節點對應的key 78 public K firstKey() { 79 return key(getFirstEntry()); 80 } 81 82 // 獲取最後一個節點對應的key 83 public K lastKey() { 84 return key(getLastEntry()); 85 } 86 87 // 將map中的全部節點新增到TreeMap中 88 public void putAll(Map<? extends K, ? extends V> map) { 89 // 獲取map的大小 90 int mapSize = map.size(); 91 // 如果TreeMap的大小是0,且map的大小不是0,且map是已排序的“key-value對” 92 if (size==0 && mapSize!=0 && map instanceof SortedMap) { 93 Comparator c = ((SortedMap)map).comparator(); 94 // 如果TreeMap和map的比較器相等; 95 // 則將map的元素全部拷貝到TreeMap中,然後返回! 96 if (c == comparator || (c != null && c.equals(comparator))) { 97 ++modCount; 98 try { 99 buildFromSorted(mapSize, map.entrySet().iterator(), 100 null, null); 101 } catch (java.io.IOException cannotHappen) { 102 } catch (ClassNotFoundException cannotHappen) { 103 } 104 return; 105 } 106 } 107 // 呼叫AbstractMap中的putAll(); 108 // AbstractMap中的putAll()又會呼叫到TreeMap的put() 109 super.putAll(map); 110 } 111 112 // 獲取TreeMap中“鍵”為key的節點 113 final Entry<K,V> getEntry(Object key) { 114 // 若“比較器”為null,則通過getEntryUsingComparator()獲取“鍵”為key的節點 115 if (comparator != null) 116 return getEntryUsingComparator(key); 117 if (key == null) 118 throw new NullPointerException(); 119 Comparable<? super K> k = (Comparable<? super K>) key; 120 // 將p設為根節點 121 Entry<K,V> p = root; 122 while (p != null) { 123 int cmp = k.compareTo(p.key); 124 // 若“p的key” < key,則p=“p的左孩子” 125 if (cmp < 0) 126 p = p.left; 127 // 若“p的key” > key,則p=“p的左孩子” 128 else if (cmp > 0) 129 p = p.right; 130 // 若“p的key” = key,則返回節點p 131 else 132 return p; 133 } 134 return null; 135 } 136 137 // 獲取TreeMap中“鍵”為key的節點(對應TreeMap的比較器不是null的情況) 138 final Entry<K,V> getEntryUsingComparator(Object key) { 139 K k = (K) key; 140 Comparator<? super K> cpr = comparator; 141 if (cpr != null) { 142 // 將p設為根節點 143 Entry<K,V> p = root; 144 while (p != null) { 145 int cmp = cpr.compare(k, p.key); 146 // 若“p的key” < key,則p=“p的左孩子” 147 if (cmp < 0) 148 p = p.left; 149 // 若“p的key” > key,則p=“p的左孩子” 150 else if (cmp > 0) 151 p = p.right; 152 // 若“p的key” = key,則返回節點p 153 else 154 return p; 155 } 156 } 157 return null; 158 } 159 160 // 獲取TreeMap中不小於key的最小的節點; 161 // 若不存在(即TreeMap中所有節點的鍵都比key大),就返回null 162 final Entry<K,V> getCeilingEntry(K key) { 163 Entry<K,V> p = root; 164 while (p != null) { 165 int cmp = compare(key, p.key); 166 // 情況一:若“p的key” > key。 167 // 若 p 存在左孩子,則設 p=“p的左孩子”; 168 // 否則,返回p 169 if (cmp < 0) { 170 if (p.left != null) 171 p = p.left; 172 else 173 return p; 174 // 情況二:若“p的key” < key。 175 } else if (cmp > 0) { 176 // 若 p 存在右孩子,則設 p=“p的右孩子” 177 if (p.right != null) { 178 p = p.right; 179 } else { 180 // 若 p 不存在右孩子,則找出 p 的後繼節點,並返回 181 // 注意:這裡返回的 “p的後繼節點”有2種可能性:第一,null;第二,TreeMap中大於key的最小的節點。 182 // 理解這一點的核心是,getCeilingEntry是從root開始遍歷的。 183 // 若getCeilingEntry能走到這一步,那麼,它之前“已經遍歷過的節點的key”都 > key。 184 // 能理解上面所說的,那麼就很容易明白,為什麼“p的後繼節點”又2種可能性了。 185 Entry<K,V> parent = p.parent; 186 Entry<K,V> ch = p; 187 while (parent != null && ch == parent.right) { 188 ch = parent; 189 parent = parent.parent; 190 } 191 return parent; 192 } 193 // 情況三:若“p的key” = key。 194 } else 195 return p; 196 } 197 return null; 198 } 199 200 // 獲取TreeMap中不大於key的最大的節點; 201 // 若不存在(即TreeMap中所有節點的鍵都比key小),就返回null 202 // getFloorEntry的原理和getCeilingEntry類似,這裡不再多說。 203 final Entry<K,V> getFloorEntry(K key) { 204 Entry<K,V> p = root; 205 while (p != null) { 206 int cmp = compare(key, p.key); 207 if (cmp > 0) { 208 if (p.right != null) 209 p = p.right; 210 else 211 return p; 212 } else if (cmp < 0) { 213 if (p.left != null) { 214 p = p.left; 215 } else { 216 Entry<K,V> parent = p.parent; 217 Entry<K,V> ch = p; 218 while (parent != null && ch == parent.left) { 219 ch = parent; 220 parent = parent.parent; 221 } 222 return parent; 223 } 224 } else 225 return p; 226 227 } 228 return null; 229 } 230 231 // 獲取TreeMap中大於key的最小的節點。 232 // 若不存在,就返回null。 233 // 請參照getCeilingEntry來對getHigherEntry進行理解。 234 final Entry<K,V> getHigherEntry(K key) { 235 Entry<K,V> p = root; 236 while (p != null) { 237 int cmp = compare(key, p.key); 238 if (cmp < 0) { 239 if (p.left != null) 240 p = p.left; 241 else 242 return p; 243 } else { 244 if (p.right != null) { 245 p = p.right; 246 } else { 247 Entry<K,V> parent = p.parent; 248 Entry<K,V> ch = p; 249 while (parent != null && ch == parent.right) { 250 ch = parent; 251 parent = parent.parent; 252 } 253 return parent; 254 } 255 } 256 } 257 return null; 258 } 259 260 // 獲取TreeMap中小於key的最大的節點。 261 // 若不存在,就返回null。 262 // 請參照getCeilingEntry來對getLowerEntry進行理解。 263 final Entry<K,V> getLowerEntry(K key) { 264 Entry<K,V> p = root; 265 while (p != null) { 266 int cmp = compare(key, p.key); 267 if (cmp > 0) { 268 if (p.right != null) 269 p = p.right; 270 else 271 return p; 272 } else { 273 if (p.left != null) { 274 p = p.left; 275 } else { 276 Entry<K,V> parent = p.parent; 277 Entry<K,V> ch = p; 278 while (parent != null && ch == parent.left) { 279 ch = parent; 280 parent = parent.parent; 281 } 282 return parent; 283 } 284 } 285 } 286 return null; 287 } 288 289 // 將“key, value”新增到TreeMap中 290 // 理解TreeMap的前提是掌握“紅黑樹”。 291 // 若理解“紅黑樹中新增節點”的演算法,則很容易理解put。 292 public V put(K key, V value) { 293 Entry<K,V> t = root; 294 // 若紅黑樹為空,則插入根節點 295 if (t == null) { 296 // TBD: 297 // 5045147: (coll) Adding null to an empty TreeSet should 298 // throw NullPointerException 299 // 300 // compare(key, key); // type check 301 root = new Entry<K,V>(key, value, null); 302 size = 1; 303 modCount++; 304 return null; 305 } 306 int cmp; 307 Entry<K,V> parent; 308 // split comparator and comparable paths 309 Comparator<? super K> cpr = comparator; 310 // 在二叉樹(紅黑樹是特殊的二叉樹)中,找到(key, value)的插入位置。 311 // 紅黑樹是以key來進行排序的,所以這裡以key來進行查詢。 312 if (cpr != null) { 313 do { 314 parent = t; 315 cmp = cpr.compare(key, t.key); 316 if (cmp < 0) 317 t = t.left; 318 else if (cmp > 0) 319 t = t.right; 320 else 321 return t.setValue(value); 322 } while (t != null); 323 } 324 else { 325 if (key == null) 326 throw new NullPointerException(); 327 Comparable<? super K> k = (Comparable<? super K>) key; 328 do { 329 parent = t; 330 cmp = k.compareTo(t.key); 331 if (cmp < 0) 332 t = t.left; 333 else if (cmp > 0) 334 t = t.right; 335 else 336 return t.setValue(value); 337 } while (t != null); 338 } 339 // 新建紅黑樹的節點(e) 340 Entry<K,V> e = new Entry<K,V>(key, value, parent); 341 if (cmp < 0) 342 parent.left = e; 343 else 344 parent.right = e; 345 // 紅黑樹插入節點後,不再是一顆紅黑樹; 346 // 這裡通過fixAfterInsertion的處理,來恢復紅黑樹的特性。 347 fixAfterInsertion(e); 348 size++; 349 modCount++; 350 return null; 351 } 352 353 // 刪除TreeMap中的鍵為key的節點,並返回節點的值 354 public V remove(Object key) { 355 // 找到鍵為key的節點 356 Entry<K,V> p = getEntry(key); 357 if (p == null) 358 return null; 359 360 // 儲存節點的值 361 V oldValue = p.value; 362 // 刪除節點 363 deleteEntry(p); 364 return oldValue; 365 } 366 367 // 清空紅黑樹 368 public void clear() { 369 modCount++; 370 size = 0; 371 root = null; 372 } 373 374 // 克隆一個TreeMap,並返回Object物件 375 public Object clone() { 376 TreeMap<K,V> clone = null; 377 try { 378 clone = (TreeMap<K,V>) super.clone(); 379 } catch (CloneNotSupportedException e) { 380 throw new InternalError(); 381 } 382 383 // Put clone into "virgin" state (except for comparator) 384 clone.root = null; 385 clone.size = 0; 386 clone.modCount = 0; 387 clone.entrySet = null; 388 clone.navigableKeySet = null; 389 clone.descendingMap = null; 390 391 // Initialize clone with our mappings 392 try { 393 clone.buildFromSorted(size, entrySet().iterator(), null, null); 394 } catch (java.io.IOException cannotHappen) { 395 } catch (ClassNotFoundException cannotHappen) { 396 } 397 398 return clone; 399 } 400 401 // 獲取第一個節點(對外介面)。 402 public Map.Entry<K,V> firstEntry() { 403 return exportEntry(getFirstEntry()); 404 } 405 406 // 獲取最後一個節點(對外介面)。 407 public Map.Entry<K,V> lastEntry() { 408 return exportEntry(getLastEntry()); 409 } 410 411 // 獲取第一個節點,並將改節點從TreeMap中刪除。 412 public Map.Entry<K,V> pollFirstEntry() { 413 // 獲取第一個節點 414 Entry<K,V> p = getFirstEntry(); 415 Map.Entry<K,V> result = exportEntry(p); 416 // 刪除第一個節點 417 if (p != null) 418 deleteEntry(p); 419 return result; 420 } 421 422 // 獲取最後一個節點,並將改節點從TreeMap中刪除。 423 public Map.Entry<K,V> pollLastEntry() { 424 // 獲取最後一個節點 425 Entry<K,V> p = getLastEntry(); 426 Map.Entry<K,V> result = exportEntry(p); 427 // 刪除最後一個節點 428 if (p != null) 429 deleteEntry(p); 430 return result; 431 } 432 433 // 返回小於key的最大的鍵值對,沒有的話返回null 434 public Map.Entry<K,V> lowerEntry(K key) { 435 return exportEntry(getLowerEntry(key)); 436 } 437 438 // 返回小於key的最大的鍵值對所對應的KEY,沒有的話返回null 439 public K lowerKey(K key) { 440 return keyOrNull(getLowerEntry(key)); 441 } 442 443 // 返回不大於key的最大的鍵值對,沒有的話返回null 444 public Map.Entry<K,V> floorEntry(K key) { 445 return exportEntry(getFloorEntry(key)); 446 } 447 448 // 返回不大於key的最大的鍵值對所對應的KEY,沒有的話返回null 449 public K floorKey(K key) { 450 return keyOrNull(getFloorEntry(key)); 451 } 452 453 // 返回不小於key的最小的鍵值對,沒有的話返回null 454 public Map.Entry<K,V> ceilingEntry(K key) { 455 return exportEntry(getCeilingEntry(key)); 456 } 457 458 // 返回不小於key的最小的鍵值對所對應的KEY,沒有的話返回null 459 public K ceilingKey(K key) { 460 return keyOrNull(getCeilingEntry(key)); 461 } 462 463 // 返回大於key的最小的鍵值對,沒有的話返回null 464 public Map.Entry<K,V> higherEntry(K key) { 465 return exportEntry(getHigherEntry(key)); 466 } 467