1. /*
  2. * @(#)TreeMap.java 1.34 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util;
  8. /**
  9. * Red-Black tree based implementation of the <tt>SortedMap</tt> interface.
  10. * This class guarantees that the map will be in ascending key order, sorted
  11. * according to the <i>natural order</i> for the key's class (see
  12. * <tt>Comparable</tt>), or by the comparator provided at creation time,
  13. * depending on which constructor is used.<p>
  14. *
  15. * This implementation provides guaranteed log(n) time cost for the
  16. * <tt>containsKey</tt>, <tt>get</tt>, <tt>put</tt> and <tt>remove</tt>
  17. * operations. Algorithms are adaptations of those in Corman, Leiserson, and
  18. * Rivest's <I>Introduction to Algorithms</I>.<p>
  19. *
  20. * Note that the ordering maintained by a sorted map (whether or not an
  21. * explicit comparator is provided) must be <i>consistent with equals</i> if
  22. * this sorted map is to correctly implement the <tt>Map</tt> interface. (See
  23. * <tt>Comparable</tt> or <tt>Comparator</tt> for a precise definition of
  24. * <i>consistent with equals</i>.) This is so because the <tt>Map</tt>
  25. * interface is defined in terms of the equals operation, but a map performs
  26. * all key comparisons using its <tt>compareTo</tt> (or <tt>compare</tt>)
  27. * method, so two keys that are deemed equal by this method are, from the
  28. * standpoint of the sorted map, equal. The behavior of a sorted map
  29. * <i>is</i> well-defined even if its ordering is inconsistent with equals; it
  30. * just fails to obey the general contract of the <tt>Map</tt> interface.<p>
  31. *
  32. * <b>Note that this implementation is not synchronized.</b> If multiple
  33. * threads access a map concurrently, and at least one of the threads modifies
  34. * the map structurally, it <i>must</i> be synchronized externally. (A
  35. * structural modification is any operation that adds or deletes one or more
  36. * mappings; merely changing the value associated with an existing key is not
  37. * a structural modification.) This is typically accomplished by
  38. * synchronizing on some object that naturally encapsulates the map. If no
  39. * such object exists, the map should be "wrapped" using the
  40. * <tt>Collections.synchronizedMap</tt> method. This is best done at creation
  41. * time, to prevent accidental unsynchronized access to the map:
  42. * <pre>
  43. * Map m = Collections.synchronizedMap(new TreeMap(...));
  44. * </pre><p>
  45. *
  46. * The iterators returned by all of this class's "collection view methods" are
  47. * <i>fail-fast</i>: if the map is structurally modified at any time after the
  48. * iterator is created, in any way except through the iterator's own
  49. * <tt>remove</tt> or <tt>add</tt> methods, the iterator throws a
  50. * <tt>ConcurrentModificationException</tt>. Thus, in the face of concurrent
  51. * modification, the iterator fails quickly and cleanly, rather than risking
  52. * arbitrary, non-deterministic behavior at an undetermined time in the
  53. * future.
  54. *
  55. * @author Josh Bloch and Doug Lea
  56. * @version 1.34, 11/29/01
  57. * @see Map
  58. * @see HashMap
  59. * @see Hashtable
  60. * @see Comparable
  61. * @see Comparator
  62. * @see Collection
  63. * @see Collections#synchronizedMap(Map)
  64. * @since JDK1.2
  65. */
  66. public class TreeMap extends AbstractMap
  67. implements SortedMap, Cloneable, java.io.Serializable
  68. {
  69. /**
  70. * The Comparator used to maintain order in this TreeMap, or
  71. * null if this TreeMap uses its elements natural ordering.
  72. *
  73. * @serial
  74. */
  75. private Comparator comparator = null;
  76. private transient Entry root = null;
  77. /**
  78. * The number of entries in the tree
  79. */
  80. private transient int size = 0;
  81. /**
  82. * The number of structural modifications to the tree.
  83. */
  84. private transient int modCount = 0;
  85. private void incrementSize() { modCount++; size++; }
  86. private void decrementSize() { modCount++; size--; }
  87. /**
  88. * Constructs a new, empty map, sorted according to the keys' natural
  89. * order. All keys inserted into the map must implement the
  90. * <tt>Comparable</tt> interface. Furthermore, all such keys must be
  91. * <i>mutually comparable</i>: <tt>k1.compareTo(k2)</tt> must not throw a
  92. * ClassCastException for any elements <tt>k1</tt> and <tt>k2</tt> in the
  93. * map. If the user attempts to put a key into the map that violates this
  94. * constraint (for example, the user attempts to put a string key into a
  95. * map whose keys are integers), the <tt>put(Object key, Object
  96. * value)</tt> call will throw a <tt>ClassCastException</tt>.
  97. *
  98. * @see Comparable
  99. */
  100. public TreeMap() {
  101. }
  102. /**
  103. * Constructs a new, empty map, sorted according to the given comparator.
  104. * All keys inserted into the map must be <i>mutually comparable</i> by
  105. * the given comparator: <tt>comparator.compare(k1, k2)</tt> must not
  106. * throw a <tt>ClassCastException</tt> for any keys <tt>k1</tt> and
  107. * <tt>k2</tt> in the map. If the user attempts to put a key into the
  108. * map that violates this constraint, the <tt>put(Object key, Object
  109. * value)</tt> call will throw a <tt>ClassCastException</tt>.
  110. */
  111. public TreeMap(Comparator c) {
  112. this.comparator = c;
  113. }
  114. /**
  115. * Constructs a new map containing the same mappings as the given map,
  116. * sorted according to the keys' <i>natural order</i>. All keys inserted
  117. * into the new map must implement the <tt>Comparable</tt> interface.
  118. * Furthermore, all such keys must be <i>mutually comparable</i>:
  119. * <tt>k1.compareTo(k2)</tt> must not throw a <tt>ClassCastException</tt>
  120. * for any elements <tt>k1</tt> and <tt>k2</tt> in the map. This method
  121. * runs in n*log(n) time.
  122. *
  123. * @throws ClassCastException the keys in t are not Comparable, or
  124. * are not mutually comparable.
  125. */
  126. public TreeMap(Map m) {
  127. putAll(m);
  128. }
  129. /**
  130. * Constructs a new map containing the same mappings as the given
  131. * <tt>SortedMap</tt>, sorted according to the same ordering. This method
  132. * runs in linear time.
  133. */
  134. public TreeMap(SortedMap m) {
  135. comparator = m.comparator();
  136. try {
  137. buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
  138. } catch (java.io.IOException cannotHappen) {
  139. } catch (ClassNotFoundException cannotHappen) {
  140. }
  141. }
  142. // Query Operations
  143. /**
  144. * Returns the number of key-value mappings in this map.
  145. *
  146. * @return the number of key-value mappings in this map.
  147. */
  148. public int size() {
  149. return size;
  150. }
  151. /**
  152. * Returns <tt>true</tt> if this map contains a mapping for the specified
  153. * key.
  154. *
  155. * @param key key whose presence in this map is to be tested.
  156. *
  157. * @return <tt>true</tt> if this map contains a mapping for the
  158. * specified key.
  159. * @throws ClassCastException if the key cannot be compared with the keys
  160. * currently in the map.
  161. * @throws NullPointerException key is <tt>null</tt> and this map uses
  162. * natural ordering, or its comparator does not tolerate
  163. * <tt>null</tt> keys.
  164. */
  165. public boolean containsKey(Object key) {
  166. return getEntry(key) != null;
  167. }
  168. /**
  169. * Returns <tt>true</tt> if this map maps one or more keys to the
  170. * specified value. More formally, returns <tt>true</tt> if and only if
  171. * this map contains at least one mapping to a value <tt>v</tt> such
  172. * that <tt>(value==null ? v==null : value.equals(v))</tt>. This
  173. * operation will probably require time linear in the Map size for most
  174. * implementations of Map.
  175. *
  176. * @param value value whose presence in this Map is to be tested.
  177. * @since JDK1.2
  178. */
  179. public boolean containsValue(Object value) {
  180. return (root==null ? false :
  181. (value==null ? valueSearchNull(root)
  182. : valueSearchNonNull(root, value)));
  183. }
  184. private boolean valueSearchNull(Entry n) {
  185. if (n.value == null)
  186. return true;
  187. // Check left and right subtrees for value
  188. return (n.left != null && valueSearchNull(n.left)) ||
  189. (n.right != null && valueSearchNull(n.right));
  190. }
  191. private boolean valueSearchNonNull(Entry n, Object value) {
  192. // Check this node for the value
  193. if (value.equals(n.value))
  194. return true;
  195. // Check left and right subtrees for value
  196. return (n.left != null && valueSearchNonNull(n.left, value)) ||
  197. (n.right != null && valueSearchNonNull(n.right, value));
  198. }
  199. /**
  200. * Returns the value to which this map maps the specified key. Returns
  201. * <tt>null</tt> if the map contains no mapping for this key. A return
  202. * value of <tt>null</tt> does not <i>necessarily</i> indicate that the
  203. * map contains no mapping for the key; it's also possible that the map
  204. * explicitly maps the key to <tt>null</tt>. The <tt>containsKey</tt>
  205. * operation may be used to distinguish these two cases.
  206. *
  207. * @param key key whose associated value is to be returned.
  208. * @return the value to which this map maps the specified key, or
  209. * <tt>null</tt> if the map contains no mapping for the key.
  210. * @throws ClassCastException key cannot be compared with the keys
  211. * currently in the map.
  212. * @throws NullPointerException key is <tt>null</tt> and this map uses
  213. * natural ordering, or its comparator does not tolerate
  214. * <tt>null</tt> keys.
  215. *
  216. * @see #containsKey(Object)
  217. */
  218. public Object get(Object key) {
  219. Entry p = getEntry(key);
  220. return (p==null ? null : p.value);
  221. }
  222. /**
  223. * Returns the comparator used to order this map, or <tt>null</tt> if this
  224. * map uses its keys' natural order.
  225. *
  226. * @return the comparator associated with this sorted map, or
  227. * <tt>null</tt> if it uses its keys' natural sort method.
  228. */
  229. public Comparator comparator() {
  230. return comparator;
  231. }
  232. /**
  233. * Returns the first (lowest) key currently in this sorted map.
  234. *
  235. * @return the first (lowest) key currently in this sorted map.
  236. * @throws NoSuchElementException Map is empty.
  237. */
  238. public Object firstKey() {
  239. return key(firstEntry());
  240. }
  241. /**
  242. * Returns the last (highest) key currently in this sorted map.
  243. *
  244. * @return the last (highest) key currently in this sorted map.
  245. * @throws NoSuchElementException Map is empty.
  246. */
  247. public Object lastKey() {
  248. return key(lastEntry());
  249. }
  250. /**
  251. * Copies all of the mappings from the specified map to this map. These
  252. * mappings replace any mappings that this map had for any of the keys
  253. * currently in the specified map.
  254. *
  255. * @param t Mappings to be stored in this map.
  256. * @throws ClassCastException class of a key or value in the specified
  257. * map prevents it from being stored in this map.
  258. *
  259. * @throws NullPointerException this map does not permit <tt>null</tt>
  260. * keys and a specified key is <tt>null</tt>.
  261. */
  262. public void putAll(Map map) {
  263. int mapSize = map.size();
  264. if (size==0 && mapSize!=0 && map instanceof SortedMap) {
  265. Comparator c = ((SortedMap)map).comparator();
  266. if (c == comparator || (c != null && c.equals(comparator))) {
  267. ++modCount;
  268. try {
  269. buildFromSorted(mapSize, map.entrySet().iterator(),
  270. null, null);
  271. } catch (java.io.IOException cannotHappen) {
  272. } catch (ClassNotFoundException cannotHappen) {
  273. }
  274. return;
  275. }
  276. }
  277. super.putAll(map);
  278. }
  279. /**
  280. * Returns this map's entry for the given key, or <tt>null</tt> if the map
  281. * does not contain an entry for the key.
  282. *
  283. * @return this map's entry for the given key, or <tt>null</tt> if the map
  284. * does not contain an entry for the key.
  285. * @throws ClassCastException if the key cannot be compared with the keys
  286. * currently in the map.
  287. * @throws NullPointerException key is <tt>null</tt> and this map uses
  288. * natural order, or its comparator does not tolerate *
  289. * <tt>null</tt> keys.
  290. */
  291. private Entry getEntry(Object key) {
  292. Entry p = root;
  293. while (p != null) {
  294. int cmp = compare(key,p.key);
  295. if (cmp == 0)
  296. return p;
  297. else if (cmp < 0)
  298. p = p.left;
  299. else
  300. p = p.right;
  301. }
  302. return null;
  303. }
  304. /**
  305. * Gets the entry corresponding to the specified key; if no such entry
  306. * exists, returns the entry for the least key greater than the specified
  307. * key; if no such entry exists (i.e., the greatest key in the Tree is less
  308. * than the specified key), returns <tt>null</tt>.
  309. */
  310. private Entry getCeilEntry(Object key) {
  311. Entry p = root;
  312. if (p==null)
  313. return null;
  314. while (true) {
  315. int cmp = compare(key, p.key);
  316. if (cmp == 0) {
  317. return p;
  318. } else if (cmp < 0) {
  319. if (p.left != null)
  320. p = p.left;
  321. else
  322. return p;
  323. } else {
  324. if (p.right != null) {
  325. p = p.right;
  326. } else {
  327. Entry parent = p.parent;
  328. Entry ch = p;
  329. while (parent != null && ch == parent.right) {
  330. ch = parent;
  331. parent = parent.parent;
  332. }
  333. return parent;
  334. }
  335. }
  336. }
  337. }
  338. /**
  339. * Returns the entry for the greatest key less than the specified key; if
  340. * no such entry exists (i.e., the least key in the Tree is greater than
  341. * the specified key), returns <tt>null</tt>.
  342. */
  343. private Entry getPrecedingEntry(Object key) {
  344. Entry p = root;
  345. if (p==null)
  346. return null;
  347. while (true) {
  348. int cmp = compare(key, p.key);
  349. if (cmp > 0) {
  350. if (p.right != null)
  351. p = p.right;
  352. else
  353. return p;
  354. } else {
  355. if (p.left != null) {
  356. p = p.left;
  357. } else {
  358. Entry parent = p.parent;
  359. Entry ch = p;
  360. while (parent != null && ch == parent.left) {
  361. ch = parent;
  362. parent = parent.parent;
  363. }
  364. return parent;
  365. }
  366. }
  367. }
  368. }
  369. /**
  370. * Returns the key corresonding to the specified Entry. Throw
  371. * NoSuchElementException if the Entry is <tt>null</tt>.
  372. */
  373. private static Object key(Entry e) {
  374. if (e==null)
  375. throw new NoSuchElementException();
  376. return e.key;
  377. }
  378. /**
  379. * Associates the specified value with the specified key in this map.
  380. * If the map previously contained a mapping for this key, the old
  381. * value is replaced.
  382. *
  383. * @param key key with which the specified value is to be associated.
  384. * @param value value to be associated with the specified key.
  385. *
  386. * @return previous value associated with specified key, or <tt>null</tt>
  387. * if there was no mapping for key. A <tt>null</tt> return can
  388. * also indicate that the map previously associated <tt>null</tt>
  389. * with the specified key.
  390. * @throws ClassCastException key cannot be compared with the keys
  391. * currently in the map.
  392. * @throws NullPointerException key is <tt>null</tt> and this map uses
  393. * natural order, or its comparator does not tolerate
  394. * <tt>null</tt> keys.
  395. */
  396. public Object put(Object key, Object value) {
  397. Entry t = root;
  398. if (t == null) {
  399. incrementSize();
  400. root = new Entry(key, value, null);
  401. return null;
  402. }
  403. while (true) {
  404. int cmp = compare(key, t.key);
  405. if (cmp == 0) {
  406. return t.setValue(value);
  407. } else if (cmp < 0) {
  408. if (t.left != null) {
  409. t = t.left;
  410. } else {
  411. incrementSize();
  412. t.left = new Entry(key, value, t);
  413. fixAfterInsertion(t.left);
  414. return null;
  415. }
  416. } else { // cmp > 0
  417. if (t.right != null) {
  418. t = t.right;
  419. } else {
  420. incrementSize();
  421. t.right = new Entry(key, value, t);
  422. fixAfterInsertion(t.right);
  423. return null;
  424. }
  425. }
  426. }
  427. }
  428. /**
  429. * Removes the mapping for this key from this TreeMap if present.
  430. *
  431. * @return previous value associated with specified key, or <tt>null</tt>
  432. * if there was no mapping for key. A <tt>null</tt> return can
  433. * also indicate that the map previously associated
  434. * <tt>null</tt> with the specified key.
  435. *
  436. * @throws ClassCastException key cannot be compared with the keys
  437. * currently in the map.
  438. * @throws NullPointerException key is <tt>null</tt> and this map uses
  439. * natural order, or its comparator does not tolerate
  440. * <tt>null</tt> keys.
  441. */
  442. public Object remove(Object key) {
  443. Entry p = getEntry(key);
  444. if (p == null)
  445. return null;
  446. Object oldValue = p.value;
  447. deleteEntry(p);
  448. return oldValue;
  449. }
  450. /**
  451. * Removes all mappings from this TreeMap.
  452. */
  453. public void clear() {
  454. modCount++;
  455. size = 0;
  456. root = null;
  457. }
  458. /**
  459. * Returns a shallow copy of this <tt>TreeMap</tt> instance. (The keys and
  460. * values themselves are not cloned.)
  461. *
  462. * @return a shallow copy of this Map.
  463. */
  464. public Object clone() {
  465. return new TreeMap(this);
  466. }
  467. // Views
  468. /**
  469. * These fields are initialized to contain an instance of the appropriate
  470. * view the first time this view is requested. The views are stateless,
  471. * so there's no reason to create more than one of each.
  472. */
  473. private transient Set keySet = null;
  474. private transient Set entrySet = null;
  475. private transient Collection values = null;
  476. /**
  477. * Returns a Set view of the keys contained in this map. The set's
  478. * iterator will return the keys in ascending order. The map is backed by
  479. * this <tt>TreeMap</tt> instance, so changes to this map are reflected in
  480. * the Set, and vice-versa. The Set supports element removal, which
  481. * removes the corresponding mapping from the map, via the
  482. * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>,
  483. * <tt>retainAll</tt>, and <tt>clear</tt> operations. It does not support
  484. * the <tt>add</tt> or <tt>addAll</tt> operations.
  485. *
  486. * @return a set view of the keys contained in this TreeMap.
  487. */
  488. public Set keySet() {
  489. if (keySet == null) {
  490. keySet = new AbstractSet() {
  491. public java.util.Iterator iterator() {
  492. return new Iterator(KEYS);
  493. }
  494. public int size() {
  495. return TreeMap.this.size();
  496. }
  497. public boolean contains(Object o) {
  498. return containsKey(o);
  499. }
  500. public boolean remove(Object o) {
  501. return TreeMap.this.remove(o) != null;
  502. }
  503. public void clear() {
  504. TreeMap.this.clear();
  505. }
  506. };
  507. }
  508. return keySet;
  509. }
  510. /**
  511. * Returns a collection view of the values contained in this map. The
  512. * collection's iterator will return the values in the order that their
  513. * corresponding keys appear in the tree. The collection is backed by
  514. * this <tt>TreeMap</tt> instance, so changes to this map are reflected in
  515. * the collection, and vice-versa. The collection supports element
  516. * removal, which removes the corresponding mapping from the map through
  517. * the <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
  518. * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
  519. * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
  520. *
  521. * @return a collection view of the values contained in this map.
  522. */
  523. public Collection values() {
  524. if (values == null) {
  525. values = new AbstractCollection() {
  526. public java.util.Iterator iterator() {
  527. return new Iterator(VALUES);
  528. }
  529. public int size() {
  530. return TreeMap.this.size();
  531. }
  532. public boolean contains(Object o) {
  533. for (Entry e = firstEntry(); e != null; e = successor(e))
  534. if (valEquals(e.getValue(), o))
  535. return true;
  536. return false;
  537. }
  538. public boolean remove(Object o) {
  539. for (Entry e = firstEntry(); e != null; e = successor(e)) {
  540. if (valEquals(e.getValue(), o)) {
  541. deleteEntry(e);
  542. return true;
  543. }
  544. }
  545. return false;
  546. }
  547. public void clear() {
  548. TreeMap.this.clear();
  549. }
  550. };
  551. }
  552. return values;
  553. }
  554. /**
  555. * Returns a set view of the mappings contained in this map. The set's
  556. * iterator returns the mappings in ascending key order. Each element in
  557. * the returned set is a <tt>Map.Entry</tt>. The set is backed by this
  558. * map, so changes to this map are reflected in the set, and vice-versa.
  559. * The set supports element removal, which removes the corresponding
  560. * mapping from the TreeMap, through the <tt>Iterator.remove</tt>,
  561. * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
  562. * <tt>clear</tt> operations. It does not support the <tt>add</tt> or
  563. * <tt>addAll</tt> operations.
  564. *
  565. * @return a set view of the mappings contained in this map.
  566. * @see Map.Entry
  567. */
  568. public Set entrySet() {
  569. if (entrySet == null) {
  570. entrySet = new AbstractSet() {
  571. public java.util.Iterator iterator() {
  572. return new Iterator(ENTRIES);
  573. }
  574. public boolean contains(Object o) {
  575. if (!(o instanceof Map.Entry))
  576. return false;
  577. Map.Entry entry = (Map.Entry)o;
  578. Object value = entry.getValue();
  579. Entry p = getEntry(entry.getKey());
  580. return p != null && valEquals(p.getValue(), value);
  581. }
  582. public boolean remove(Object o) {
  583. if (!(o instanceof Map.Entry))
  584. return false;
  585. Map.Entry entry = (Map.Entry)o;
  586. Object value = entry.getValue();
  587. Entry p = getEntry(entry.getKey());
  588. if (p != null && valEquals(p.getValue(), value)) {
  589. deleteEntry(p);
  590. return true;
  591. }
  592. return false;
  593. }
  594. public int size() {
  595. return TreeMap.this.size();
  596. }
  597. public void clear() {
  598. TreeMap.this.clear();
  599. }
  600. };
  601. }
  602. return entrySet;
  603. }
  604. /**
  605. * Returns a view of the portion of this map whose keys range from
  606. * <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>, exclusive. (If
  607. * <tt>fromKey</tt> and <tt>toKey</tt> are equal, the returned sorted map
  608. * is empty.) The returned sorted map is backed by this map, so changes
  609. * in the returned sorted map are reflected in this map, and vice-versa.
  610. * The returned sorted map supports all optional map operations.<p>
  611. *
  612. * The sorted map returned by this method will throw an
  613. * <tt>IllegalArgumentException</tt> if the user attempts to insert a key
  614. * less than <tt>fromKey</tt> or greater than or equal to
  615. * <tt>toKey</tt>.<p>
  616. *
  617. * Note: this method always returns a <i>half-open range</i> (which
  618. * includes its low endpoint but not its high endpoint). If you need a
  619. * <i>closed range</i> (which includes both endpoints), and the key type
  620. * allows for calculation of the successor a given key, merely request the
  621. * subrange from <tt>lowEndpoint</tt> to <tt>successor(highEndpoint)</tt>.
  622. * For example, suppose that <tt>m</tt> is a sorted map whose keys are
  623. * strings. The following idiom obtains a view containing all of the
  624. * key-value mappings in <tt>m</tt> whose keys are between <tt>low</tt>
  625. * and <tt>high</tt>, inclusive:
  626. * <pre> SortedMap sub = m.submap(low, high+"\0");</pre>
  627. * A similar technique can be used to generate an <i>open range</i> (which
  628. * contains neither endpoint). The following idiom obtains a view
  629. * containing all of the key-value mappings in <tt>m</tt> whose keys are
  630. * between <tt>low</tt> and <tt>high</tt>, exclusive:
  631. * <pre> SortedMap sub = m.subMap(low+"\0", high);</pre>
  632. *
  633. * @param fromKey low endpoint (inclusive) of the subMap.
  634. * @param toKey high endpoint (exclusive) of the subMap.
  635. *
  636. * @return a view of the portion of this map whose keys range from
  637. * <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>, exclusive.
  638. *
  639. * @throws NullPointerException if <tt>fromKey</tt> or <tt>toKey</tt> is
  640. * <tt>null</tt> and this map uses natural order, or its
  641. * comparator does not tolerate <tt>null</tt> keys.
  642. *
  643. * @throws IllegalArgumentException if <tt>fromKey</tt> is greater than
  644. * <tt>toKey</tt>.
  645. */
  646. public SortedMap subMap(Object fromKey, Object toKey) {
  647. return new SubMap(fromKey, toKey);
  648. }
  649. /**
  650. * Returns a view of the portion of this map whose keys are strictly less
  651. * than <tt>toKey</tt>. The returned sorted map is backed by this map, so
  652. * changes in the returned sorted map are reflected in this map, and
  653. * vice-versa. The returned sorted map supports all optional map
  654. * operations.<p>
  655. *
  656. * The sorted map returned by this method will throw an
  657. * <tt>IllegalArgumentException</tt> if the user attempts to insert a key
  658. * greater than or equal to <tt>toKey</tt>.<p>
  659. *
  660. * Note: this method always returns a view that does not contain its
  661. * (high) endpoint. If you need a view that does contain this endpoint,
  662. * and the key type allows for calculation of the successor a given key,
  663. * merely request a headMap bounded by <tt>successor(highEndpoint)</tt>.
  664. * For example, suppose that suppose that <tt>m</tt> is a sorted map whose
  665. * keys are strings. The following idiom obtains a view containing all of
  666. * the key-value mappings in <tt>m</tt> whose keys are less than or equal
  667. * to <tt>high</tt>:
  668. * <pre>
  669. * SortedMap head = m.headMap(high+"\0");
  670. * </pre>
  671. *
  672. * @param toKey high endpoint (exclusive) of the headMap.
  673. * @return a view of the portion of this map whose keys are strictly
  674. * less than <tt>toKey</tt>.
  675. * @throws NullPointerException if <tt>toKey</tt> is <tt>null</tt> and
  676. * this map uses natural order, or its comparator does * not
  677. * tolerate <tt>null</tt> keys.
  678. */
  679. public SortedMap headMap(Object toKey) {
  680. return new SubMap(toKey, true);
  681. }
  682. /**
  683. * Returns a view of the portion of this map whose keys are greater than
  684. * or equal to <tt>fromKey</tt>. The returned sorted map is backed by
  685. * this map, so changes in the returned sorted map are reflected in this
  686. * map, and vice-versa. The returned sorted map supports all optional map
  687. * operations.<p>
  688. *
  689. * The sorted map returned by this method will throw an
  690. * <tt>IllegalArgumentException</tt> if the user attempts to insert a key
  691. * less than <tt>fromKey</tt>.<p>
  692. *
  693. * Note: this method always returns a view that contains its (low)
  694. * endpoint. If you need a view that does not contain this endpoint, and
  695. * the element type allows for calculation of the successor a given value,
  696. * merely request a tailMap bounded by <tt>successor(lowEndpoint)</tt>.
  697. * For For example, suppose that suppose that <tt>m</tt> is a sorted map
  698. * whose keys are strings. The following idiom obtains a view containing
  699. * all of the key-value mappings in <tt>m</tt> whose keys are strictly
  700. * greater than <tt>low</tt>: <pre>
  701. * SortedMap tail = m.tailMap(low+"\0");
  702. * </pre>
  703. *
  704. * @param fromKey low endpoint (inclusive) of the tailMap.
  705. * @return a view of the portion of this map whose keys are greater
  706. * than or equal to <tt>fromKey</tt>.
  707. * @throws NullPointerException fromKey is <tt>null</tt> and this
  708. * map uses natural ordering, or its comparator does
  709. * not tolerate <tt>null</tt> keys.
  710. */
  711. public SortedMap tailMap(Object fromKey) {
  712. return new SubMap(fromKey, false);
  713. }
  714. private class SubMap extends AbstractMap
  715. implements SortedMap, java.io.Serializable {
  716. private static final long serialVersionUID = -6520786458950516097L;
  717. /**
  718. * fromKey is significant only if fromStart is false. Similarly,
  719. * toKey is significant only if toStart is false.
  720. */
  721. private boolean fromStart = false, toEnd = false;
  722. private Object fromKey, toKey;
  723. SubMap(Object fromKey, Object toKey) {
  724. if (compare(fromKey, toKey) > 0)
  725. throw new IllegalArgumentException("fromKey > toKey");
  726. this.fromKey = fromKey;
  727. this.toKey = toKey;
  728. }
  729. SubMap(Object key, boolean headMap) {
  730. if (headMap) {
  731. fromStart = true;
  732. toKey = key;
  733. } else {
  734. toEnd = true;
  735. fromKey = key;
  736. }
  737. }
  738. SubMap(boolean fromStart, Object fromKey, boolean toEnd, Object toKey){
  739. this.fromStart = fromStart;
  740. this.fromKey= fromKey;
  741. this.toEnd = toEnd;
  742. this.toKey = toKey;
  743. }
  744. public boolean isEmpty() {
  745. return entrySet.isEmpty();
  746. }
  747. public boolean containsKey(Object key) {
  748. return inRange(key) && TreeMap.this.containsKey(key);
  749. }
  750. public Object get(Object key) {
  751. if (!inRange(key))
  752. return null;
  753. return TreeMap.this.get(key);
  754. }
  755. public Object put(Object key, Object value) {
  756. if (!inRange(key))
  757. throw new IllegalArgumentException("key out of range");
  758. return TreeMap.this.put(key, value);
  759. }
  760. public Comparator comparator() {
  761. return comparator;
  762. }
  763. public Object firstKey() {
  764. return key(fromStart ? firstEntry() : getCeilEntry(fromKey));
  765. }
  766. public Object lastKey() {
  767. return key(toEnd ? lastEntry() : getPrecedingEntry(toKey));
  768. }
  769. private transient Set entrySet = new EntrySetView();
  770. public Set entrySet() {
  771. return entrySet;
  772. }
  773. private class EntrySetView extends AbstractSet {
  774. private transient int size = -1, sizeModCount;
  775. public int size() {
  776. if (size == -1 || sizeModCount != TreeMap.this.modCount) {
  777. size = 0; sizeModCount = TreeMap.this.modCount;
  778. java.util.Iterator i = iterator();
  779. while (i.hasNext()) {
  780. size++;
  781. i.next();
  782. }
  783. }
  784. return size;
  785. }
  786. public boolean isEmpty() {
  787. return !iterator().hasNext();
  788. }
  789. public boolean contains(Object o) {
  790. if (!(o instanceof Map.Entry))
  791. return false;
  792. Map.Entry entry = (Map.Entry)o;
  793. Object key = entry.getKey();
  794. if (!inRange(key))
  795. return false;
  796. Entry node = getEntry(key);
  797. return node != null &&
  798. valEquals(node.getValue(), entry.getValue());
  799. }
  800. public boolean remove(Object o) {
  801. if (!(o instanceof Map.Entry))
  802. return false;
  803. Map.Entry entry = (Map.Entry)o;
  804. Object key = entry.getKey();
  805. if (!inRange(key))
  806. return false;
  807. Entry node = getEntry(key);
  808. if (node!=null && valEquals(node.getValue(),entry.getValue())){
  809. deleteEntry(node);
  810. return true;
  811. }
  812. return false;
  813. }
  814. public java.util.Iterator iterator() {
  815. return new Iterator(
  816. (fromStart ? firstEntry() : getCeilEntry(fromKey)),
  817. (toEnd ? null : getCeilEntry(toKey)));
  818. }
  819. }
  820. public SortedMap subMap(Object fromKey, Object toKey) {
  821. if (!inRange(fromKey))
  822. throw new IllegalArgumentException("fromKey out of range");
  823. if (!inRange2(toKey))
  824. throw new IllegalArgumentException("toKey out of range");
  825. return new SubMap(fromKey, toKey);
  826. }
  827. public SortedMap headMap(Object toKey) {
  828. if (!inRange2(toKey))
  829. throw new IllegalArgumentException("toKey out of range");
  830. return new SubMap(fromStart, fromKey, false, toKey);
  831. }
  832. public SortedMap tailMap(Object fromKey) {
  833. if (!inRange(fromKey))
  834. throw new IllegalArgumentException("fromKey out of range");
  835. return new SubMap(false, fromKey, toEnd, toKey);
  836. }
  837. private boolean inRange(Object key) {
  838. return (fromStart || compare(key, fromKey) >= 0) &&
  839. (toEnd || compare(key, toKey) < 0);
  840. }
  841. // This form allows the high endpoint (as well as all legit keys)
  842. private boolean inRange2(Object key) {
  843. return (fromStart || compare(key, fromKey) >= 0) &&
  844. (toEnd || compare(key, toKey) <= 0);
  845. }
  846. }
  847. // Types of Iterators
  848. private static final int KEYS = 0;
  849. private static final int VALUES = 1;
  850. private static final int ENTRIES = 2;
  851. /**
  852. * TreeMap Iterator.
  853. */
  854. private class Iterator implements java.util.Iterator {
  855. private int type;
  856. private int expectedModCount = TreeMap.this.modCount;
  857. private Entry lastReturned = null;
  858. private Entry next;
  859. private Entry firstExcluded = null;
  860. Iterator(int type) {
  861. this.type = type;
  862. next = firstEntry();
  863. }
  864. Iterator(Entry first, Entry firstExcluded) {
  865. type = ENTRIES;
  866. next = first;
  867. this.firstExcluded = firstExcluded;
  868. }
  869. public boolean hasNext() {
  870. return next != firstExcluded;
  871. }
  872. public Object next() {
  873. if (next == firstExcluded)
  874. throw new NoSuchElementException();
  875. if (modCount != expectedModCount)
  876. throw new ConcurrentModificationException();
  877. lastReturned = next;
  878. next = successor(next);
  879. return (type == KEYS ? lastReturned.key :
  880. (type == VALUES ? lastReturned.value : lastReturned));
  881. }
  882. public void remove() {
  883. if (lastReturned == null)
  884. throw new IllegalStateException();
  885. if (modCount != expectedModCount)
  886. throw new ConcurrentModificationException();
  887. deleteEntry(lastReturned);
  888. expectedModCount++;
  889. lastReturned = null;
  890. }
  891. }
  892. /**
  893. * Compares two keys using the correct comparison method for this TreeMap.
  894. */
  895. private int compare(Object k1, Object k2) {
  896. return (comparator==null ? ((Comparable)k1).compareTo(k2)
  897. : comparator.compare(k1, k2));
  898. }
  899. /**
  900. * Test two values for equality. Differs from o1.equals(o2) only in
  901. * that it copes with with <tt>null</tt> o1 properly.
  902. */
  903. private static boolean valEquals(Object o1, Object o2) {
  904. return (o1==null ? o2==null : o1.equals(o2));
  905. }
  906. private static final boolean RED = false;
  907. private static final boolean BLACK = true;
  908. /**
  909. * Node in the Tree. Doubles as a means to pass key-value pairs back to
  910. * user (see Map.Entry).
  911. */
  912. static class Entry implements Map.Entry {
  913. Object key;
  914. Object value;
  915. Entry left = null;
  916. Entry right = null;
  917. Entry parent;
  918. boolean color = BLACK;
  919. /**
  920. * Make a new cell with given key, value, and parent, and with <tt>null</tt>
  921. * child links, and BLACK color.
  922. */
  923. Entry(Object key, Object value, Entry parent) {
  924. this.key = key;
  925. this.value = value;
  926. this.parent = parent;
  927. }
  928. /**
  929. * Returns the key.
  930. *
  931. * @return the key.
  932. */
  933. public Object getKey() {
  934. return key;
  935. }
  936. /**
  937. * Returns the value associated with the key.
  938. *
  939. * @return the value associated with the key.
  940. */
  941. public Object getValue() {
  942. return value;
  943. }
  944. /**
  945. * Replaces the value currently associated with the key with the given
  946. * value.
  947. *
  948. * @return the value associated with the key before this method was
  949. * called.
  950. */
  951. public Object setValue(Object value) {
  952. Object oldValue = this.value;
  953. this.value = value;
  954. return oldValue;
  955. }
  956. public boolean equals(Object o) {
  957. if (!(o instanceof Map.Entry))
  958. return false;
  959. Map.Entry e = (Map.Entry)o;
  960. return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
  961. }
  962. public int hashCode() {
  963. int keyHash = (key==null ? 0 : key.hashCode());
  964. int valueHash = (value==null ? 0 : value.hashCode());
  965. return keyHash ^ valueHash;
  966. }
  967. public String toString() {
  968. return key + "=" + value;
  969. }
  970. }
  971. /**
  972. * Returns the first Entry in the TreeMap (according to the TreeMap's
  973. * key-sort function). Returns null if the TreeMap is empty.
  974. */
  975. private Entry firstEntry() {
  976. Entry p = root;
  977. if (p != null)
  978. while (p.left != null)
  979. p = p.left;
  980. return p;
  981. }
  982. /**
  983. * Returns the last Entry in the TreeMap (according to the TreeMap's
  984. * key-sort function). Returns null if the TreeMap is empty.
  985. */
  986. private Entry lastEntry() {
  987. Entry p = root;
  988. if (p != null)
  989. while (p.right != null)
  990. p = p.right;
  991. return p;
  992. }
  993. /**
  994. * Returns the successor of the specified Entry, or null if no such.
  995. */
  996. private Entry successor(Entry t) {
  997. if (t == null)
  998. return null;
  999. else if (t.right != null) {
  1000. Entry p = t.right;
  1001. while (p.left != null)
  1002. p = p.left;
  1003. return p;
  1004. } else {
  1005. Entry p = t.parent;
  1006. Entry ch = t;
  1007. while (p != null && ch == p.right) {
  1008. ch = p;
  1009. p = p.parent;
  1010. }
  1011. return p;
  1012. }
  1013. }
  1014. /**
  1015. * Balancing operations.
  1016. *
  1017. * Implementations of rebalancings during insertion and deletion are
  1018. * slightly different than the CLR version. Rather than using dummy
  1019. * nilnodes, we use a set of accessors that deal properly with null. They
  1020. * are used to avoid messiness surrounding nullness checks in the main
  1021. * algorithms.
  1022. */
  1023. private static boolean colorOf(Entry p) {
  1024. return (p == null ? BLACK : p.color);
  1025. }
  1026. private static Entry parentOf(Entry p) {
  1027. return (p == null ? null: p.parent);
  1028. }
  1029. private static void setColor(Entry p, boolean c) {
  1030. if (p != null) p.color = c;
  1031. }
  1032. private static Entry leftOf(Entry p) {
  1033. return (p == null)? null: p.left;
  1034. }
  1035. private static Entry rightOf(Entry p) {
  1036. return (p == null)? null: p.right;
  1037. }
  1038. /** From CLR **/
  1039. private void rotateLeft(Entry p) {
  1040. Entry r = p.right;
  1041. p.right = r.left;
  1042. if (r.left != null)
  1043. r.left.parent = p;
  1044. r.parent = p.parent;
  1045. if (p.parent == null)
  1046. root = r;
  1047. else if (p.parent.left == p)
  1048. p.parent.left = r;
  1049. else
  1050. p.parent.right = r;
  1051. r.left = p;
  1052. p.parent = r;
  1053. }
  1054. /** From CLR **/
  1055. private void rotateRight(Entry p) {
  1056. Entry l = p.left;
  1057. p.left = l.right;
  1058. if (l.right != null) l.right.parent = p;
  1059. l.parent = p.parent;
  1060. if (p.parent == null)
  1061. root = l;
  1062. else if (p.parent.right == p)
  1063. p.parent.right = l;
  1064. else p.parent.left = l;
  1065. l.right = p;
  1066. p.parent = l;
  1067. }
  1068. /** From CLR **/
  1069. private void fixAfterInsertion(Entry x) {
  1070. x.color = RED;
  1071. while (x != null && x != root && x.parent.color == RED) {
  1072. if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
  1073. Entry y = rightOf(parentOf(parentOf(x)));
  1074. if (colorOf(y) == RED) {
  1075. setColor(parentOf(x), BLACK);
  1076. setColor(y, BLACK);
  1077. setColor(parentOf(parentOf(x)), RED);
  1078. x = parentOf(parentOf(x));
  1079. } else {
  1080. if (x == rightOf(parentOf(x))) {
  1081. x = parentOf(x);
  1082. rotateLeft(x);
  1083. }
  1084. setColor(parentOf(x), BLACK);
  1085. setColor(parentOf(parentOf(x)), RED);
  1086. if (parentOf(parentOf(x)) != null)
  1087. rotateRight(parentOf(parentOf(x)));
  1088. }
  1089. } else {
  1090. Entry y = leftOf(parentOf(parentOf(x)));
  1091. if (colorOf(y) == RED) {
  1092. setColor(parentOf(x), BLACK);
  1093. setColor(y, BLACK);
  1094. setColor(parentOf(parentOf(x)), RED);
  1095. x = parentOf(parentOf(x));
  1096. } else {
  1097. if (x == leftOf(parentOf(x))) {
  1098. x = parentOf(x);
  1099. rotateRight(x);
  1100. }
  1101. setColor(parentOf(x), BLACK);
  1102. setColor(parentOf(parentOf(x)), RED);
  1103. if (parentOf(parentOf(x)) != null)
  1104. rotateLeft(parentOf(parentOf(x)));
  1105. }
  1106. }
  1107. }
  1108. root.color = BLACK;
  1109. }
  1110. /**
  1111. * Delete node p, and then rebalance the tree.
  1112. */
  1113. private void deleteEntry(Entry p) {
  1114. decrementSize();
  1115. // If strictly internal, first swap position with successor.
  1116. if (p.left != null && p.right != null) {
  1117. Entry s = successor(p);
  1118. swapPosition(s, p);
  1119. }
  1120. // Start fixup at replacement node, if it exists.
  1121. Entry replacement = (p.left != null ? p.left : p.right);
  1122. if (replacement != null) {
  1123. // Link replacement to parent
  1124. replacement.parent = p.parent;
  1125. if (p.parent == null)
  1126. root = replacement;
  1127. else if (p == p.parent.left)
  1128. p.parent.left = replacement;
  1129. else
  1130. p.parent.right = replacement;
  1131. // Null out links so they are OK to use by fixAfterDeletion.
  1132. p.left = p.right = p.parent = null;
  1133. // Fix replacement
  1134. if (p.color == BLACK)
  1135. fixAfterDeletion(replacement);
  1136. } else if (p.parent == null) { // return if we are the only node.
  1137. root = null;
  1138. } else { // No children. Use self as phantom replacement and unlink.
  1139. if (p.color == BLACK)
  1140. fixAfterDeletion(p);
  1141. if (p.parent != null) {
  1142. if (p == p.parent.left)
  1143. p.parent.left = null;
  1144. else if (p == p.parent.right)
  1145. p.parent.right = null;
  1146. p.parent = null;
  1147. }
  1148. }
  1149. }
  1150. /** From CLR **/
  1151. private void fixAfterDeletion(Entry x) {
  1152. while (x != root && colorOf(x) == BLACK) {
  1153. if (x == leftOf(parentOf(x))) {
  1154. Entry sib = rightOf(parentOf(x));
  1155. if (colorOf(sib) == RED) {
  1156. setColor(sib, BLACK);
  1157. setColor(parentOf(x), RED);
  1158. rotateLeft(parentOf(x));
  1159. sib = rightOf(parentOf(x));
  1160. }
  1161. if (colorOf(leftOf(sib)) == BLACK &&
  1162. colorOf(rightOf(sib)) == BLACK) {
  1163. setColor(sib, RED);
  1164. x = parentOf(x);
  1165. } else {
  1166. if (colorOf(rightOf(sib)) == BLACK) {
  1167. setColor(leftOf(sib), BLACK);
  1168. setColor(sib, RED);
  1169. rotateRight(sib);
  1170. sib = rightOf(parentOf(x));
  1171. }
  1172. setColor(sib, colorOf(parentOf(x)));
  1173. setColor(parentOf(x), BLACK);
  1174. setColor(rightOf(sib), BLACK);
  1175. rotateLeft(parentOf(x));
  1176. x = root;
  1177. }
  1178. } else { // symmetric
  1179. Entry sib = leftOf(parentOf(x));
  1180. if (colorOf(sib) == RED) {
  1181. setColor(sib, BLACK);
  1182. setColor(parentOf(x), RED);
  1183. rotateRight(parentOf(x));
  1184. sib = leftOf(parentOf(x));
  1185. }
  1186. if (colorOf(rightOf(sib)) == BLACK &&
  1187. colorOf(leftOf(sib)) == BLACK) {
  1188. setColor(sib, RED);
  1189. x = parentOf(x);
  1190. } else {
  1191. if (colorOf(leftOf(sib)) == BLACK) {
  1192. setColor(rightOf(sib), BLACK);
  1193. setColor(sib, RED);
  1194. rotateLeft(sib);
  1195. sib = leftOf(parentOf(x));
  1196. }
  1197. setColor(sib, colorOf(parentOf(x)));
  1198. setColor(parentOf(x), BLACK);
  1199. setColor(leftOf(sib), BLACK);
  1200. rotateRight(parentOf(x));
  1201. x = root;
  1202. }
  1203. }
  1204. }
  1205. setColor(x, BLACK);
  1206. }
  1207. /**
  1208. * Swap the linkages of two nodes in a tree.
  1209. */
  1210. private void swapPosition(Entry x, Entry y) {
  1211. // Save initial values.
  1212. Entry px = x.parent, lx = x.left, rx = x.right;
  1213. Entry py = y.parent, ly = y.left, ry = y.right;
  1214. boolean xWasLeftChild = px != null && x == px.left;
  1215. boolean yWasLeftChild = py != null && y == py.left;
  1216. // Swap, handling special cases of one being the other's parent.
  1217. if (x == py) { // x was y's parent
  1218. x.parent = y;
  1219. if (yWasLeftChild) {
  1220. y.left = x;
  1221. y.right = rx;
  1222. } else {
  1223. y.right = x;
  1224. y.left = lx;
  1225. }
  1226. } else {
  1227. x.parent = py;
  1228. if (py != null) {
  1229. if (yWasLeftChild)
  1230. py.left = x;
  1231. else
  1232. py.right = x;
  1233. }
  1234. y.left = lx;
  1235. y.right = rx;
  1236. }
  1237. if (y == px) { // y was x's parent
  1238. y.parent = x;
  1239. if (xWasLeftChild) {
  1240. x.left = y;
  1241. x.right = ry;
  1242. } else {
  1243. x.right = y;
  1244. x.left = ly;
  1245. }
  1246. } else {
  1247. y.parent = px;
  1248. if (px != null) {
  1249. if (xWasLeftChild)
  1250. px.left = y;
  1251. else
  1252. px.right = y;
  1253. }
  1254. x.left = ly;
  1255. x.right = ry;
  1256. }
  1257. // Fix children's parent pointers
  1258. if (x.left != null)
  1259. x.left.parent = x;
  1260. if (x.right != null)
  1261. x.right.parent = x;
  1262. if (y.left != null)
  1263. y.left.parent = y;
  1264. if (y.right != null)
  1265. y.right.parent = y;
  1266. // Swap colors
  1267. boolean c = x.color;
  1268. x.color = y.color;
  1269. y.color = c;
  1270. // Check if root changed
  1271. if (root == x)
  1272. root = y;
  1273. else if (root == y)
  1274. root = x;
  1275. }
  1276. private static final long serialVersionUID = 919286545866124006L;
  1277. /**
  1278. * Save the state of the <tt>TreeMap</tt> instance to a stream (i.e.,
  1279. * serialize it).
  1280. *
  1281. * @serialData The <i>size</i> of the TreeMap (the number of key-value
  1282. * mappings) is emitted (int), followed by the key (Object)
  1283. * and value (Object) for each key-value mapping represented
  1284. * by the TreeMap. The key-value mappings are emitted in
  1285. * key-order (as determined by the TreeMap's Comparator,
  1286. * or by the keys' natural ordering if the TreeMap has no
  1287. * Comparator).
  1288. */
  1289. private void writeObject(java.io.ObjectOutputStream s)
  1290. throws java.io.IOException {
  1291. // Write out the Comparator and any hidden stuff
  1292. s.defaultWriteObject();
  1293. // Write out size (number of Mappings)
  1294. s.writeInt(size);
  1295. // Write out keys and values (alternating)
  1296. for (java.util.Iterator i = entrySet().iterator(); i.hasNext(); ) {
  1297. Entry e = (Entry)i.next();
  1298. s.writeObject(e.key);
  1299. s.writeObject(e.value);
  1300. }
  1301. }
  1302. /**
  1303. * Reconstitute the <tt>TreeMap</tt> instance from a stream (i.e.,
  1304. * deserialize it).
  1305. */
  1306. private void readObject(final java.io.ObjectInputStream s)
  1307. throws java.io.IOException, ClassNotFoundException {
  1308. // Read in the Comparator and any hidden stuff
  1309. s.defaultReadObject();
  1310. // Read in size
  1311. int size = s.readInt();
  1312. buildFromSorted(size, null, s, null);
  1313. }
  1314. /** Intended to be called only from TreeSet.readObject **/
  1315. void readTreeSet(int size, java.io.ObjectInputStream s, Object defaultVal)
  1316. throws java.io.IOException, ClassNotFoundException {
  1317. buildFromSorted(size, null, s, defaultVal);
  1318. }
  1319. /** Intended to be called only from TreeSet.addAll **/
  1320. void addAllForTreeSet(SortedSet set, Object defaultVal) {
  1321. try {
  1322. buildFromSorted(set.size(), set.iterator(), null, defaultVal);
  1323. } catch (java.io.IOException cannotHappen) {
  1324. } catch (ClassNotFoundException cannotHappen) {
  1325. }
  1326. }
  1327. /**
  1328. * Linear time tree building algorithm from sorted data. Can accept keys
  1329. * and/or values from iterator or stream. This leads to too many
  1330. * parameters, but seems better than alternatives. The four formats
  1331. * that this method accepts are:
  1332. *
  1333. * 1) An iterator of Map.Entries. (it != null, defaultVal == null).
  1334. * 2) An iterator of keys. (it != null, defaultVal != null).
  1335. * 3) A stream of alternating serialized keys and values.
  1336. * (it == null, defaultVal == null).
  1337. * 4) A stream of serialized keys. (it == null, defaultVal != null).
  1338. *
  1339. * It is assumed that the comparator of the TreeMap is already set prior
  1340. * to calling this method.
  1341. *
  1342. * @param size the number of keys (or key-value pairs) to be read from
  1343. * the iterator or stream.
  1344. * @param it If non-null, new entries are created from entries
  1345. * or keys read from this iterator.
  1346. * @param it If non-null, new entries are created from keys and
  1347. * possibly values read from this stream in serialized form.
  1348. * Exactly one of it and str should be non-null.
  1349. * @param defaultVal if non-null, this default value is used for
  1350. * each value in the map. If null, each value is read from
  1351. * iterator or stream, as described above.
  1352. * @throws IOException propagated from stream reads. This cannot
  1353. * occur if str is null.
  1354. * @throws ClassNotFoundException propagated from readObject.
  1355. * This cannot occur if str is null.
  1356. */
  1357. private void buildFromSorted(int size, java.util.Iterator it,
  1358. java.io.ObjectInputStream str,
  1359. Object defaultVal)
  1360. throws java.io.IOException, ClassNotFoundException {
  1361. this.size = size;
  1362. root = buildFromSorted(0, 0, size-1, computeRedLevel(size),
  1363. it, str, defaultVal);
  1364. }
  1365. /**
  1366. * Recursive "helper method" that does the real work of the
  1367. * of the previous method. Identically named parameters have
  1368. * identical definitions. Additional parameters are documented below.
  1369. * It is assumed that the comparator and size fields of the TreeMap are
  1370. * already set prior to calling this method. (It ignores both fields.)
  1371. *
  1372. * @param level the current level of tree. Initial call should be 0.
  1373. * @param lo the first element index of this subtree. Initial should be 0.
  1374. * @param hi the last element index of this subtree. Initial should be
  1375. * size-1.
  1376. * @param redLevel the level at which nodes should be red.
  1377. * Must be equal to computeRedLevel for tree of this size.
  1378. */
  1379. private static Entry buildFromSorted(int level, int lo, int hi,
  1380. int redLevel,
  1381. java.util.Iterator it,
  1382. java.io.ObjectInputStream str,
  1383. Object defaultVal)
  1384. throws java.io.IOException, ClassNotFoundException {
  1385. /*
  1386. * Strategy: The root is the middlemost element. To get to it, we
  1387. * have to first recursively construct the entire left subtree,
  1388. * so as to grab all of its elements. We can then proceed with right
  1389. * subtree.
  1390. *
  1391. * The lo and hi arguments are the minimum and maximum
  1392. * indices to pull out of the iterator or stream for current subtree.
  1393. * They are not actually indexed, we just proceed sequentially,
  1394. * ensuring that items are extracted in corresponding order.
  1395. */
  1396. if (hi < lo) return null;
  1397. int mid = (lo + hi) / 2;
  1398. Entry left = null;
  1399. if (lo < mid)
  1400. left = buildFromSorted(level+1, lo, mid - 1, redLevel,
  1401. it, str, defaultVal);
  1402. // extract key and/or value from iterator or stream
  1403. Object key;
  1404. Object value;
  1405. if (it != null) { // use iterator
  1406. if (defaultVal==null) {
  1407. Map.Entry entry = (Map.Entry) it.next();
  1408. key = entry.getKey();
  1409. value = entry.getValue();
  1410. } else {
  1411. key = it.next();
  1412. value = defaultVal;
  1413. }
  1414. } else { // use stream
  1415. key = str.readObject();
  1416. value = (defaultVal != null ? defaultVal : str.readObject());
  1417. }
  1418. Entry middle = new Entry(key, value, null);
  1419. // color nodes in non-full bottommost level red
  1420. if (level == redLevel)
  1421. middle.color = RED;
  1422. if (left != null) {
  1423. middle.left = left;
  1424. left.parent = middle;
  1425. }
  1426. if (mid < hi) {
  1427. Entry right = buildFromSorted(level+1, mid+1, hi, redLevel,
  1428. it, str, defaultVal);
  1429. middle.right = right;
  1430. right.parent = middle;
  1431. }
  1432. return middle;
  1433. }
  1434. /**
  1435. * Find the level down to which to assign all nodes BLACK. This is the
  1436. * last `full' level of the complete binary tree produced by
  1437. * buildTree. The remaining nodes are colored RED. (This makes a `nice'
  1438. * set of color assignments wrt future insertions.) This level number is
  1439. * computed by finding the number of splits needed to reach the zeroeth
  1440. * node. (The answer is ~lg(N), but in any case must be computed by same
  1441. * quick O(lg(N)) loop.)
  1442. */
  1443. private static int computeRedLevel(int sz) {
  1444. int level = 0;
  1445. for (int m = sz - 1; m >= 0; m = m / 2 - 1)
  1446. level++;
  1447. return level;
  1448. }
  1449. }