source: trunk/src/gcc/libjava/java/util/TreeMap.java@ 64

Last change on this file since 64 was 2, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 51.1 KB
Line 
1/* TreeMap.java -- a class providing a basic Red-Black Tree data structure,
2 mapping Object --> Object
3 Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4
5This file is part of GNU Classpath.
6
7GNU Classpath is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU Classpath is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Classpath; see the file COPYING. If not, write to the
19Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
2002111-1307 USA.
21
22Linking this library statically or dynamically with other modules is
23making a combined work based on this library. Thus, the terms and
24conditions of the GNU General Public License cover the whole
25combination.
26
27As a special exception, the copyright holders of this library give you
28permission to link this library with independent modules to produce an
29executable, regardless of the license terms of these independent
30modules, and to copy and distribute the resulting executable under
31terms of your choice, provided that you also meet, for each linked
32independent module, the terms and conditions of the license of that
33module. An independent module is a module which is not derived from
34or based on this library. If you modify this library, you may extend
35this exception to your version of the library, but you are not
36obligated to do so. If you do not wish to do so, delete this
37exception statement from your version. */
38
39
40package java.util;
41
42import java.io.Serializable;
43import java.io.ObjectOutputStream;
44import java.io.ObjectInputStream;
45import java.io.IOException;
46
47/**
48 * This class provides a red-black tree implementation of the SortedMap
49 * interface. Elements in the Map will be sorted by either a user-provided
50 * Comparator object, or by the natural ordering of the keys.
51 *
52 * The algorithms are adopted from Corman, Leiserson, and Rivest's
53 * <i>Introduction to Algorithms.</i> TreeMap guarantees O(log n)
54 * insertion and deletion of elements. That being said, there is a large
55 * enough constant coefficient in front of that "log n" (overhead involved
56 * in keeping the tree balanced), that TreeMap may not be the best choice
57 * for small collections. If something is already sorted, you may want to
58 * just use a LinkedHashMap to maintain the order while providing O(1) access.
59 *
60 * TreeMap is a part of the JDK1.2 Collections API. Null keys are allowed
61 * only if a Comparator is used which can deal with them; natural ordering
62 * cannot cope with null. Null values are always allowed. Note that the
63 * ordering must be <i>consistent with equals</i> to correctly implement
64 * the Map interface. If this condition is violated, the map is still
65 * well-behaved, but you may have suprising results when comparing it to
66 * other maps.<p>
67 *
68 * This implementation is not synchronized. If you need to share this between
69 * multiple threads, do something like:<br>
70 * <code>SortedMap m
71 * = Collections.synchronizedSortedMap(new TreeMap(...));</code><p>
72 *
73 * The iterators are <i>fail-fast</i>, meaning that any structural
74 * modification, except for <code>remove()</code> called on the iterator
75 * itself, cause the iterator to throw a
76 * <code>ConcurrentModificationException</code> rather than exhibit
77 * non-deterministic behavior.
78 *
79 * @author Jon Zeppieri
80 * @author Bryce McKinlay
81 * @author Eric Blake <[email protected]>
82 * @see Map
83 * @see HashMap
84 * @see Hashtable
85 * @see LinkedHashMap
86 * @see Comparable
87 * @see Comparator
88 * @see Collection
89 * @see Collections#synchronizedSortedMap(SortedMap)
90 * @since 1.2
91 * @status updated to 1.4
92 */
93public class TreeMap extends AbstractMap
94 implements SortedMap, Cloneable, Serializable
95{
96 // Implementation note:
97 // A red-black tree is a binary search tree with the additional properties
98 // that all paths to a leaf node visit the same number of black nodes,
99 // and no red node has red children. To avoid some null-pointer checks,
100 // we use the special node nil which is always black, has no relatives,
101 // and has key and value of null (but is not equal to a mapping of null).
102
103 /**
104 * Compatible with JDK 1.2.
105 */
106 private static final long serialVersionUID = 919286545866124006L;
107
108 /**
109 * Color status of a node. Package visible for use by nested classes.
110 */
111 static final int RED = -1,
112 BLACK = 1;
113
114 /**
115 * Sentinal node, used to avoid null checks for corner cases and make the
116 * delete rebalance code simpler. The rebalance code must never assign
117 * the parent, left, or right of nil, but may safely reassign the color
118 * to be black. This object must never be used as a key in a TreeMap, or
119 * it will break bounds checking of a SubMap.
120 */
121 static final Node nil = new Node(null, null, BLACK);
122 static
123 {
124 // Nil is self-referential, so we must initialize it after creation.
125 nil.parent = nil;
126 nil.left = nil;
127 nil.right = nil;
128 }
129
130 /**
131 * The root node of this TreeMap.
132 */
133 private transient Node root = nil;
134
135 /**
136 * The size of this TreeMap. Package visible for use by nested classes.
137 */
138 transient int size;
139
140 /**
141 * The cache for {@link #entrySet()}.
142 */
143 private transient Set entries;
144
145 /**
146 * Counts the number of modifications this TreeMap has undergone, used
147 * by Iterators to know when to throw ConcurrentModificationExceptions.
148 * Package visible for use by nested classes.
149 */
150 transient int modCount;
151
152 /**
153 * This TreeMap's comparator, or null for natural ordering.
154 * Package visible for use by nested classes.
155 * @serial the comparator ordering this tree, or null
156 */
157 final Comparator comparator;
158
159 /**
160 * Class to represent an entry in the tree. Holds a single key-value pair,
161 * plus pointers to parent and child nodes.
162 *
163 * @author Eric Blake <[email protected]>
164 */
165 private static final class Node extends BasicMapEntry
166 {
167 // All fields package visible for use by nested classes.
168 /** The color of this node. */
169 int color;
170
171 /** The left child node. */
172 Node left = nil;
173 /** The right child node. */
174 Node right = nil;
175 /** The parent node. */
176 Node parent = nil;
177
178 /**
179 * Simple constructor.
180 * @param key the key
181 * @param value the value
182 */
183 Node(Object key, Object value, int color)
184 {
185 super(key, value);
186 this.color = color;
187 }
188 }
189
190 /**
191 * Instantiate a new TreeMap with no elements, using the keys' natural
192 * ordering to sort. All entries in the map must have a key which implements
193 * Comparable, and which are <i>mutually comparable</i>, otherwise map
194 * operations may throw a {@link ClassCastException}. Attempts to use
195 * a null key will throw a {@link NullPointerException}.
196 *
197 * @see Comparable
198 */
199 public TreeMap()
200 {
201 this((Comparator) null);
202 }
203
204 /**
205 * Instantiate a new TreeMap with no elements, using the provided comparator
206 * to sort. All entries in the map must have keys which are mutually
207 * comparable by the Comparator, otherwise map operations may throw a
208 * {@link ClassCastException}.
209 *
210 * @param comparator the sort order for the keys of this map, or null
211 * for the natural order
212 */
213 public TreeMap(Comparator c)
214 {
215 comparator = c;
216 }
217
218 /**
219 * Instantiate a new TreeMap, initializing it with all of the elements in
220 * the provided Map. The elements will be sorted using the natural
221 * ordering of the keys. This algorithm runs in n*log(n) time. All entries
222 * in the map must have keys which implement Comparable and are mutually
223 * comparable, otherwise map operations may throw a
224 * {@link ClassCastException}.
225 *
226 * @param map a Map, whose entries will be put into this TreeMap
227 * @throws ClassCastException if the keys in the provided Map are not
228 * comparable
229 * @throws NullPointerException if map is null
230 * @see Comparable
231 */
232 public TreeMap(Map map)
233 {
234 this((Comparator) null);
235 putAll(map);
236 }
237
238 /**
239 * Instantiate a new TreeMap, initializing it with all of the elements in
240 * the provided SortedMap. The elements will be sorted using the same
241 * comparator as in the provided SortedMap. This runs in linear time.
242 *
243 * @param sm a SortedMap, whose entries will be put into this TreeMap
244 * @throws NullPointerException if sm is null
245 */
246 public TreeMap(SortedMap sm)
247 {
248 this(sm.comparator());
249 int pos = sm.size();
250 Iterator itr = sm.entrySet().iterator();
251
252 fabricateTree(pos);
253 Node node = firstNode();
254
255 while (--pos >= 0)
256 {
257 Map.Entry me = (Map.Entry) itr.next();
258 node.key = me.getKey();
259 node.value = me.getValue();
260 node = successor(node);
261 }
262 }
263
264 /**
265 * Clears the Map so it has no keys. This is O(1).
266 */
267 public void clear()
268 {
269 if (size > 0)
270 {
271 modCount++;
272 root = nil;
273 size = 0;
274 }
275 }
276
277 /**
278 * Returns a shallow clone of this TreeMap. The Map itself is cloned,
279 * but its contents are not.
280 *
281 * @return the clone
282 */
283 public Object clone()
284 {
285 TreeMap copy = null;
286 try
287 {
288 copy = (TreeMap) super.clone();
289 }
290 catch (CloneNotSupportedException x)
291 {
292 }
293 copy.entries = null;
294 copy.fabricateTree(size);
295
296 Node node = firstNode();
297 Node cnode = copy.firstNode();
298
299 while (node != nil)
300 {
301 cnode.key = node.key;
302 cnode.value = node.value;
303 node = successor(node);
304 cnode = copy.successor(cnode);
305 }
306 return copy;
307 }
308
309 /**
310 * Return the comparator used to sort this map, or null if it is by
311 * natural order.
312 *
313 * @return the map's comparator
314 */
315 public Comparator comparator()
316 {
317 return comparator;
318 }
319
320 /**
321 * Returns true if the map contains a mapping for the given key.
322 *
323 * @param key the key to look for
324 * @return true if the key has a mapping
325 * @throws ClassCastException if key is not comparable to map elements
326 * @throws NullPointerException if key is null and the comparator is not
327 * tolerant of nulls
328 */
329 public boolean containsKey(Object key)
330 {
331 return getNode(key) != nil;
332 }
333
334 /**
335 * Returns true if the map contains at least one mapping to the given value.
336 * This requires linear time.
337 *
338 * @param value the value to look for
339 * @return true if the value appears in a mapping
340 */
341 public boolean containsValue(Object value)
342 {
343 Node node = firstNode();
344 while (node != nil)
345 {
346 if (equals(value, node.value))
347 return true;
348 node = successor(node);
349 }
350 return false;
351 }
352
353 /**
354 * Returns a "set view" of this TreeMap's entries. The set is backed by
355 * the TreeMap, so changes in one show up in the other. The set supports
356 * element removal, but not element addition.<p>
357 *
358 * Note that the iterators for all three views, from keySet(), entrySet(),
359 * and values(), traverse the TreeMap in sorted sequence.
360 *
361 * @return a set view of the entries
362 * @see #keySet()
363 * @see #values()
364 * @see Map.Entry
365 */
366 public Set entrySet()
367 {
368 if (entries == null)
369 // Create an AbstractSet with custom implementations of those methods
370 // that can be overriden easily and efficiently.
371 entries = new AbstractSet()
372 {
373 public int size()
374 {
375 return size;
376 }
377
378 public Iterator iterator()
379 {
380 return new TreeIterator(ENTRIES);
381 }
382
383 public void clear()
384 {
385 TreeMap.this.clear();
386 }
387
388 public boolean contains(Object o)
389 {
390 if (! (o instanceof Map.Entry))
391 return false;
392 Map.Entry me = (Map.Entry) o;
393 Node n = getNode(me.getKey());
394 return n != nil && AbstractSet.equals(me.getValue(), n.value);
395 }
396
397 public boolean remove(Object o)
398 {
399 if (! (o instanceof Map.Entry))
400 return false;
401 Map.Entry me = (Map.Entry) o;
402 Node n = getNode(me.getKey());
403 if (n != nil && AbstractSet.equals(me.getValue(), n.value))
404 {
405 removeNode(n);
406 return true;
407 }
408 return false;
409 }
410 };
411 return entries;
412 }
413
414 /**
415 * Returns the first (lowest) key in the map.
416 *
417 * @return the first key
418 * @throws NoSuchElementException if the map is empty
419 */
420 public Object firstKey()
421 {
422 if (root == nil)
423 throw new NoSuchElementException();
424 return firstNode().key;
425 }
426
427 /**
428 * Return the value in this TreeMap associated with the supplied key,
429 * or <code>null</code> if the key maps to nothing. NOTE: Since the value
430 * could also be null, you must use containsKey to see if this key
431 * actually maps to something.
432 *
433 * @param key the key for which to fetch an associated value
434 * @return what the key maps to, if present
435 * @throws ClassCastException if key is not comparable to elements in the map
436 * @throws NullPointerException if key is null but the comparator does not
437 * tolerate nulls
438 * @see #put(Object, Object)
439 * @see #containsKey(Object)
440 */
441 public Object get(Object key)
442 {
443 // Exploit fact that nil.value == null.
444 return getNode(key).value;
445 }
446
447 /**
448 * Returns a view of this Map including all entries with keys less than
449 * <code>toKey</code>. The returned map is backed by the original, so changes
450 * in one appear in the other. The submap will throw an
451 * {@link IllegalArgumentException} for any attempt to access or add an
452 * element beyond the specified cutoff. The returned map does not include
453 * the endpoint; if you want inclusion, pass the successor element.
454 *
455 * @param toKey the (exclusive) cutoff point
456 * @return a view of the map less than the cutoff
457 * @throws ClassCastException if <code>toKey</code> is not compatible with
458 * the comparator (or is not Comparable, for natural ordering)
459 * @throws NullPointerException if toKey is null, but the comparator does not
460 * tolerate null elements
461 */
462 public SortedMap headMap(Object toKey)
463 {
464 return new SubMap(nil, toKey);
465 }
466
467 /**
468 * Returns a "set view" of this TreeMap's keys. The set is backed by the
469 * TreeMap, so changes in one show up in the other. The set supports
470 * element removal, but not element addition.
471 *
472 * @return a set view of the keys
473 * @see #values()
474 * @see #entrySet()
475 */
476 public Set keySet()
477 {
478 if (keys == null)
479 // Create an AbstractSet with custom implementations of those methods
480 // that can be overriden easily and efficiently.
481 keys = new AbstractSet()
482 {
483 public int size()
484 {
485 return size;
486 }
487
488 public Iterator iterator()
489 {
490 return new TreeIterator(KEYS);
491 }
492
493 public void clear()
494 {
495 TreeMap.this.clear();
496 }
497
498 public boolean contains(Object o)
499 {
500 return containsKey(o);
501 }
502
503 public boolean remove(Object key)
504 {
505 Node n = getNode(key);
506 if (n == nil)
507 return false;
508 removeNode(n);
509 return true;
510 }
511 };
512 return keys;
513 }
514
515 /**
516 * Returns the last (highest) key in the map.
517 *
518 * @return the last key
519 * @throws NoSuchElementException if the map is empty
520 */
521 public Object lastKey()
522 {
523 if (root == nil)
524 throw new NoSuchElementException("empty");
525 return lastNode().key;
526 }
527
528 /**
529 * Puts the supplied value into the Map, mapped by the supplied key.
530 * The value may be retrieved by any object which <code>equals()</code>
531 * this key. NOTE: Since the prior value could also be null, you must
532 * first use containsKey if you want to see if you are replacing the
533 * key's mapping.
534 *
535 * @param key the key used to locate the value
536 * @param value the value to be stored in the HashMap
537 * @return the prior mapping of the key, or null if there was none
538 * @throws ClassCastException if key is not comparable to current map keys
539 * @throws NullPointerException if key is null, but the comparator does
540 * not tolerate nulls
541 * @see #get(Object)
542 * @see Object#equals(Object)
543 */
544 public Object put(Object key, Object value)
545 {
546 Node current = root;
547 Node parent = nil;
548 int comparison = 0;
549
550 // Find new node's parent.
551 while (current != nil)
552 {
553 parent = current;
554 comparison = compare(key, current.key);
555 if (comparison > 0)
556 current = current.right;
557 else if (comparison < 0)
558 current = current.left;
559 else // Key already in tree.
560 return current.setValue(value);
561 }
562
563 // Set up new node.
564 Node n = new Node(key, value, RED);
565 n.parent = parent;
566
567 // Insert node in tree.
568 modCount++;
569 size++;
570 if (parent == nil)
571 {
572 // Special case inserting into an empty tree.
573 root = n;
574 return null;
575 }
576 if (comparison > 0)
577 parent.right = n;
578 else
579 parent.left = n;
580
581 // Rebalance after insert.
582 insertFixup(n);
583 return null;
584 }
585
586 /**
587 * Copies all elements of the given map into this hashtable. If this table
588 * already has a mapping for a key, the new mapping replaces the current
589 * one.
590 *
591 * @param m the map to be hashed into this
592 * @throws ClassCastException if a key in m is not comparable with keys
593 * in the map
594 * @throws NullPointerException if a key in m is null, and the comparator
595 * does not tolerate nulls
596 */
597 public void putAll(Map m)
598 {
599 Iterator itr = m.entrySet().iterator();
600 int pos = m.size();
601 while (--pos >= 0)
602 {
603 Map.Entry e = (Map.Entry) itr.next();
604 put(e.getKey(), e.getValue());
605 }
606 }
607
608 /**
609 * Removes from the TreeMap and returns the value which is mapped by the
610 * supplied key. If the key maps to nothing, then the TreeMap remains
611 * unchanged, and <code>null</code> is returned. NOTE: Since the value
612 * could also be null, you must use containsKey to see if you are
613 * actually removing a mapping.
614 *
615 * @param key the key used to locate the value to remove
616 * @return whatever the key mapped to, if present
617 * @throws ClassCastException if key is not comparable to current map keys
618 * @throws NullPointerException if key is null, but the comparator does
619 * not tolerate nulls
620 */
621 public Object remove(Object key)
622 {
623 Node n = getNode(key);
624 if (n == nil)
625 return null;
626 removeNode(n);
627 return n.value;
628 }
629
630 /**
631 * Returns the number of key-value mappings currently in this Map.
632 *
633 * @return the size
634 */
635 public int size()
636 {
637 return size;
638 }
639
640 /**
641 * Returns a view of this Map including all entries with keys greater or
642 * equal to <code>fromKey</code> and less than <code>toKey</code> (a
643 * half-open interval). The returned map is backed by the original, so
644 * changes in one appear in the other. The submap will throw an
645 * {@link IllegalArgumentException} for any attempt to access or add an
646 * element beyond the specified cutoffs. The returned map includes the low
647 * endpoint but not the high; if you want to reverse this behavior on
648 * either end, pass in the successor element.
649 *
650 * @param fromKey the (inclusive) low cutoff point
651 * @param toKey the (exclusive) high cutoff point
652 * @return a view of the map between the cutoffs
653 * @throws ClassCastException if either cutoff is not compatible with
654 * the comparator (or is not Comparable, for natural ordering)
655 * @throws NullPointerException if fromKey or toKey is null, but the
656 * comparator does not tolerate null elements
657 * @throws IllegalArgumentException if fromKey is greater than toKey
658 */
659 public SortedMap subMap(Object fromKey, Object toKey)
660 {
661 return new SubMap(fromKey, toKey);
662 }
663
664 /**
665 * Returns a view of this Map including all entries with keys greater or
666 * equal to <code>fromKey</code>. The returned map is backed by the
667 * original, so changes in one appear in the other. The submap will throw an
668 * {@link IllegalArgumentException} for any attempt to access or add an
669 * element beyond the specified cutoff. The returned map includes the
670 * endpoint; if you want to exclude it, pass in the successor element.
671 *
672 * @param fromKey the (inclusive) low cutoff point
673 * @return a view of the map above the cutoff
674 * @throws ClassCastException if <code>fromKey</code> is not compatible with
675 * the comparator (or is not Comparable, for natural ordering)
676 * @throws NullPointerException if fromKey is null, but the comparator
677 * does not tolerate null elements
678 */
679 public SortedMap tailMap(Object fromKey)
680 {
681 return new SubMap(fromKey, nil);
682 }
683
684 /**
685 * Returns a "collection view" (or "bag view") of this TreeMap's values.
686 * The collection is backed by the TreeMap, so changes in one show up
687 * in the other. The collection supports element removal, but not element
688 * addition.
689 *
690 * @return a bag view of the values
691 * @see #keySet()
692 * @see #entrySet()
693 */
694 public Collection values()
695 {
696 if (values == null)
697 // We don't bother overriding many of the optional methods, as doing so
698 // wouldn't provide any significant performance advantage.
699 values = new AbstractCollection()
700 {
701 public int size()
702 {
703 return size;
704 }
705
706 public Iterator iterator()
707 {
708 return new TreeIterator(VALUES);
709 }
710
711 public void clear()
712 {
713 TreeMap.this.clear();
714 }
715 };
716 return values;
717 }
718
719 /**
720 * Compares two elements by the set comparator, or by natural ordering.
721 * Package visible for use by nested classes.
722 *
723 * @param o1 the first object
724 * @param o2 the second object
725 * @throws ClassCastException if o1 and o2 are not mutually comparable,
726 * or are not Comparable with natural ordering
727 * @throws NullPointerException if o1 or o2 is null with natural ordering
728 */
729 final int compare(Object o1, Object o2)
730 {
731 return (comparator == null
732 ? ((Comparable) o1).compareTo(o2)
733 : comparator.compare(o1, o2));
734 }
735
736 /**
737 * Maintain red-black balance after deleting a node.
738 *
739 * @param node the child of the node just deleted, possibly nil
740 * @param parent the parent of the node just deleted, never nil
741 */
742 private void deleteFixup(Node node, Node parent)
743 {
744 // if (parent == nil)
745 // throw new InternalError();
746 // If a black node has been removed, we need to rebalance to avoid
747 // violating the "same number of black nodes on any path" rule. If
748 // node is red, we can simply recolor it black and all is well.
749 while (node != root && node.color == BLACK)
750 {
751 if (node == parent.left)
752 {
753 // Rebalance left side.
754 Node sibling = parent.right;
755 // if (sibling == nil)
756 // throw new InternalError();
757 if (sibling.color == RED)
758 {
759 // Case 1: Sibling is red.
760 // Recolor sibling and parent, and rotate parent left.
761 sibling.color = BLACK;
762 parent.color = RED;
763 rotateLeft(parent);
764 sibling = parent.right;
765 }
766
767 if (sibling.left.color == BLACK && sibling.right.color == BLACK)
768 {
769 // Case 2: Sibling has no red children.
770 // Recolor sibling, and move to parent.
771 sibling.color = RED;
772 node = parent;
773 parent = parent.parent;
774 }
775 else
776 {
777 if (sibling.right.color == BLACK)
778 {
779 // Case 3: Sibling has red left child.
780 // Recolor sibling and left child, rotate sibling right.
781 sibling.left.color = BLACK;
782 sibling.color = RED;
783 rotateRight(sibling);
784 sibling = parent.right;
785 }
786 // Case 4: Sibling has red right child. Recolor sibling,
787 // right child, and parent, and rotate parent left.
788 sibling.color = parent.color;
789 parent.color = BLACK;
790 sibling.right.color = BLACK;
791 rotateLeft(parent);
792 node = root; // Finished.
793 }
794 }
795 else
796 {
797 // Symmetric "mirror" of left-side case.
798 Node sibling = parent.left;
799 // if (sibling == nil)
800 // throw new InternalError();
801 if (sibling.color == RED)
802 {
803 // Case 1: Sibling is red.
804 // Recolor sibling and parent, and rotate parent right.
805 sibling.color = BLACK;
806 parent.color = RED;
807 rotateRight(parent);
808 sibling = parent.left;
809 }
810
811 if (sibling.right.color == BLACK && sibling.left.color == BLACK)
812 {
813 // Case 2: Sibling has no red children.
814 // Recolor sibling, and move to parent.
815 sibling.color = RED;
816 node = parent;
817 parent = parent.parent;
818 }
819 else
820 {
821 if (sibling.left.color == BLACK)
822 {
823 // Case 3: Sibling has red right child.
824 // Recolor sibling and right child, rotate sibling left.
825 sibling.right.color = BLACK;
826 sibling.color = RED;
827 rotateLeft(sibling);
828 sibling = parent.left;
829 }
830 // Case 4: Sibling has red left child. Recolor sibling,
831 // left child, and parent, and rotate parent right.
832 sibling.color = parent.color;
833 parent.color = BLACK;
834 sibling.left.color = BLACK;
835 rotateRight(parent);
836 node = root; // Finished.
837 }
838 }
839 }
840 node.color = BLACK;
841 }
842
843 /**
844 * Construct a perfectly balanced tree consisting of n "blank" nodes. This
845 * permits a tree to be generated from pre-sorted input in linear time.
846 *
847 * @param count the number of blank nodes, non-negative
848 */
849 private void fabricateTree(final int count)
850 {
851 if (count == 0)
852 return;
853
854 // We color every row of nodes black, except for the overflow nodes.
855 // I believe that this is the optimal arrangement. We construct the tree
856 // in place by temporarily linking each node to the next node in the row,
857 // then updating those links to the children when working on the next row.
858
859 // Make the root node.
860 root = new Node(null, null, BLACK);
861 size = count;
862 Node row = root;
863 int rowsize;
864
865 // Fill each row that is completely full of nodes.
866 for (rowsize = 2; rowsize + rowsize < count; rowsize <<= 1)
867 {
868 Node parent = row;
869 Node last = null;
870 for (int i = 0; i < rowsize; i += 2)
871 {
872 Node left = new Node(null, null, BLACK);
873 Node right = new Node(null, null, BLACK);
874 left.parent = parent;
875 left.right = right;
876 right.parent = parent;
877 parent.left = left;
878 Node next = parent.right;
879 parent.right = right;
880 parent = next;
881 if (last != null)
882 last.right = left;
883 last = right;
884 }
885 row = row.left;
886 }
887
888 // Now do the partial final row in red.
889 int overflow = count - rowsize;
890 Node parent = row;
891 int i;
892 for (i = 0; i < overflow; i += 2)
893 {
894 Node left = new Node(null, null, RED);
895 Node right = new Node(null, null, RED);
896 left.parent = parent;
897 right.parent = parent;
898 parent.left = left;
899 Node next = parent.right;
900 parent.right = right;
901 parent = next;
902 }
903 // Add a lone left node if necessary.
904 if (i - overflow == 0)
905 {
906 Node left = new Node(null, null, RED);
907 left.parent = parent;
908 parent.left = left;
909 parent = parent.right;
910 left.parent.right = nil;
911 }
912 // Unlink the remaining nodes of the previous row.
913 while (parent != nil)
914 {
915 Node next = parent.right;
916 parent.right = nil;
917 parent = next;
918 }
919 }
920
921 /**
922 * Returns the first sorted node in the map, or nil if empty. Package
923 * visible for use by nested classes.
924 *
925 * @return the first node
926 */
927 final Node firstNode()
928 {
929 // Exploit fact that nil.left == nil.
930 Node node = root;
931 while (node.left != nil)
932 node = node.left;
933 return node;
934 }
935
936 /**
937 * Return the TreeMap.Node associated with key, or the nil node if no such
938 * node exists in the tree. Package visible for use by nested classes.
939 *
940 * @param key the key to search for
941 * @return the node where the key is found, or nil
942 */
943 final Node getNode(Object key)
944 {
945 Node current = root;
946 while (current != nil)
947 {
948 int comparison = compare(key, current.key);
949 if (comparison > 0)
950 current = current.right;
951 else if (comparison < 0)
952 current = current.left;
953 else
954 return current;
955 }
956 return current;
957 }
958
959 /**
960 * Find the "highest" node which is &lt; key. If key is nil, return last
961 * node. Package visible for use by nested classes.
962 *
963 * @param key the upper bound, exclusive
964 * @return the previous node
965 */
966 final Node highestLessThan(Object key)
967 {
968 if (key == nil)
969 return lastNode();
970
971 Node last = nil;
972 Node current = root;
973 int comparison = 0;
974
975 while (current != nil)
976 {
977 last = current;
978 comparison = compare(key, current.key);
979 if (comparison > 0)
980 current = current.right;
981 else if (comparison < 0)
982 current = current.left;
983 else // Exact match.
984 return predecessor(last);
985 }
986 return comparison <= 0 ? predecessor(last) : last;
987 }
988
989 /**
990 * Maintain red-black balance after inserting a new node.
991 *
992 * @param n the newly inserted node
993 */
994 private void insertFixup(Node n)
995 {
996 // Only need to rebalance when parent is a RED node, and while at least
997 // 2 levels deep into the tree (ie: node has a grandparent). Remember
998 // that nil.color == BLACK.
999 while (n.parent.color == RED && n.parent.parent != nil)
1000 {
1001 if (n.parent == n.parent.parent.left)
1002 {
1003 Node uncle = n.parent.parent.right;
1004 // Uncle may be nil, in which case it is BLACK.
1005 if (uncle.color == RED)
1006 {
1007 // Case 1. Uncle is RED: Change colors of parent, uncle,
1008 // and grandparent, and move n to grandparent.
1009 n.parent.color = BLACK;
1010 uncle.color = BLACK;
1011 uncle.parent.color = RED;
1012 n = uncle.parent;
1013 }
1014 else
1015 {
1016 if (n == n.parent.right)
1017 {
1018 // Case 2. Uncle is BLACK and x is right child.
1019 // Move n to parent, and rotate n left.
1020 n = n.parent;
1021 rotateLeft(n);
1022 }
1023 // Case 3. Uncle is BLACK and x is left child.
1024 // Recolor parent, grandparent, and rotate grandparent right.
1025 n.parent.color = BLACK;
1026 n.parent.parent.color = RED;
1027 rotateRight(n.parent.parent);
1028 }
1029 }
1030 else
1031 {
1032 // Mirror image of above code.
1033 Node uncle = n.parent.parent.left;
1034 // Uncle may be nil, in which case it is BLACK.
1035 if (uncle.color == RED)
1036 {
1037 // Case 1. Uncle is RED: Change colors of parent, uncle,
1038 // and grandparent, and move n to grandparent.
1039 n.parent.color = BLACK;
1040 uncle.color = BLACK;
1041 uncle.parent.color = RED;
1042 n = uncle.parent;
1043 }
1044 else
1045 {
1046 if (n == n.parent.left)
1047 {
1048 // Case 2. Uncle is BLACK and x is left child.
1049 // Move n to parent, and rotate n right.
1050 n = n.parent;
1051 rotateRight(n);
1052 }
1053 // Case 3. Uncle is BLACK and x is right child.
1054 // Recolor parent, grandparent, and rotate grandparent left.
1055 n.parent.color = BLACK;
1056 n.parent.parent.color = RED;
1057 rotateLeft(n.parent.parent);
1058 }
1059 }
1060 }
1061 root.color = BLACK;
1062 }
1063
1064 /**
1065 * Returns the last sorted node in the map, or nil if empty.
1066 *
1067 * @return the last node
1068 */
1069 private Node lastNode()
1070 {
1071 // Exploit fact that nil.right == nil.
1072 Node node = root;
1073 while (node.right != nil)
1074 node = node.right;
1075 return node;
1076 }
1077
1078 /**
1079 * Find the "lowest" node which is &gt;= key. If key is nil, return either
1080 * nil or the first node, depending on the parameter first.
1081 * Package visible for use by nested classes.
1082 *
1083 * @param key the lower bound, inclusive
1084 * @param first true to return the first element instead of nil for nil key
1085 * @return the next node
1086 */
1087 final Node lowestGreaterThan(Object key, boolean first)
1088 {
1089 if (key == nil)
1090 return first ? firstNode() : nil;
1091
1092 Node last = nil;
1093 Node current = root;
1094 int comparison = 0;
1095
1096 while (current != nil)
1097 {
1098 last = current;
1099 comparison = compare(key, current.key);
1100 if (comparison > 0)
1101 current = current.right;
1102 else if (comparison < 0)
1103 current = current.left;
1104 else
1105 return current;
1106 }
1107 return comparison > 0 ? successor(last) : last;
1108 }
1109
1110 /**
1111 * Return the node preceding the given one, or nil if there isn't one.
1112 *
1113 * @param node the current node, not nil
1114 * @return the prior node in sorted order
1115 */
1116 private Node predecessor(Node node)
1117 {
1118 if (node.left != nil)
1119 {
1120 node = node.left;
1121 while (node.right != nil)
1122 node = node.right;
1123 return node;
1124 }
1125
1126 Node parent = node.parent;
1127 // Exploit fact that nil.left == nil and node is non-nil.
1128 while (node == parent.left)
1129 {
1130 node = parent;
1131 parent = node.parent;
1132 }
1133 return parent;
1134 }
1135
1136 /**
1137 * Construct a tree from sorted keys in linear time. Package visible for
1138 * use by TreeSet.
1139 *
1140 * @param s the stream to read from
1141 * @param count the number of keys to read
1142 * @param readValue true to read values, false to insert "" as the value
1143 * @throws ClassNotFoundException if the underlying stream fails
1144 * @throws IOException if the underlying stream fails
1145 * @see #readObject(ObjectInputStream)
1146 * @see TreeSet#readObject(ObjectInputStream)
1147 */
1148 final void putFromObjStream(ObjectInputStream s, int count,
1149 boolean readValues)
1150 throws IOException, ClassNotFoundException
1151 {
1152 fabricateTree(count);
1153 Node node = firstNode();
1154
1155 while (--count >= 0)
1156 {
1157 node.key = s.readObject();
1158 node.value = readValues ? s.readObject() : "";
1159 node = successor(node);
1160 }
1161 }
1162
1163 /**
1164 * Construct a tree from sorted keys in linear time, with values of "".
1165 * Package visible for use by TreeSet.
1166 *
1167 * @param keys the iterator over the sorted keys
1168 * @param count the number of nodes to insert
1169 * @see TreeSet#TreeSet(SortedSet)
1170 */
1171 final void putKeysLinear(Iterator keys, int count)
1172 {
1173 fabricateTree(count);
1174 Node node = firstNode();
1175
1176 while (--count >= 0)
1177 {
1178 node.key = keys.next();
1179 node.value = "";
1180 node = successor(node);
1181 }
1182 }
1183
1184 /**
1185 * Deserializes this object from the given stream.
1186 *
1187 * @param s the stream to read from
1188 * @throws ClassNotFoundException if the underlying stream fails
1189 * @throws IOException if the underlying stream fails
1190 * @serialData the <i>size</i> (int), followed by key (Object) and value
1191 * (Object) pairs in sorted order
1192 */
1193 private void readObject(ObjectInputStream s)
1194 throws IOException, ClassNotFoundException
1195 {
1196 s.defaultReadObject();
1197 int size = s.readInt();
1198 putFromObjStream(s, size, true);
1199 }
1200
1201 /**
1202 * Remove node from tree. This will increment modCount and decrement size.
1203 * Node must exist in the tree. Package visible for use by nested classes.
1204 *
1205 * @param node the node to remove
1206 */
1207 final void removeNode(Node node)
1208 {
1209 Node splice;
1210 Node child;
1211
1212 modCount++;
1213 size--;
1214
1215 // Find splice, the node at the position to actually remove from the tree.
1216 if (node.left == nil)
1217 {
1218 // Node to be deleted has 0 or 1 children.
1219 splice = node;
1220 child = node.right;
1221 }
1222 else if (node.right == nil)
1223 {
1224 // Node to be deleted has 1 child.
1225 splice = node;
1226 child = node.left;
1227 }
1228 else
1229 {
1230 // Node has 2 children. Splice is node's predecessor, and we swap
1231 // its contents into node.
1232 splice = node.left;
1233 while (splice.right != nil)
1234 splice = splice.right;
1235 child = splice.left;
1236 node.key = splice.key;
1237 node.value = splice.value;
1238 }
1239
1240 // Unlink splice from the tree.
1241 Node parent = splice.parent;
1242 if (child != nil)
1243 child.parent = parent;
1244 if (parent == nil)
1245 {
1246 // Special case for 0 or 1 node remaining.
1247 root = child;
1248 return;
1249 }
1250 if (splice == parent.left)
1251 parent.left = child;
1252 else
1253 parent.right = child;
1254
1255 if (splice.color == BLACK)
1256 deleteFixup(child, parent);
1257 }
1258
1259 /**
1260 * Rotate node n to the left.
1261 *
1262 * @param node the node to rotate
1263 */
1264 private void rotateLeft(Node node)
1265 {
1266 Node child = node.right;
1267 // if (node == nil || child == nil)
1268 // throw new InternalError();
1269
1270 // Establish node.right link.
1271 node.right = child.left;
1272 if (child.left != nil)
1273 child.left.parent = node;
1274
1275 // Establish child->parent link.
1276 child.parent = node.parent;
1277 if (node.parent != nil)
1278 {
1279 if (node == node.parent.left)
1280 node.parent.left = child;
1281 else
1282 node.parent.right = child;
1283 }
1284 else
1285 root = child;
1286
1287 // Link n and child.
1288 child.left = node;
1289 node.parent = child;
1290 }
1291
1292 /**
1293 * Rotate node n to the right.
1294 *
1295 * @param node the node to rotate
1296 */
1297 private void rotateRight(Node node)
1298 {
1299 Node child = node.left;
1300 // if (node == nil || child == nil)
1301 // throw new InternalError();
1302
1303 // Establish node.left link.
1304 node.left = child.right;
1305 if (child.right != nil)
1306 child.right.parent = node;
1307
1308 // Establish child->parent link.
1309 child.parent = node.parent;
1310 if (node.parent != nil)
1311 {
1312 if (node == node.parent.right)
1313 node.parent.right = child;
1314 else
1315 node.parent.left = child;
1316 }
1317 else
1318 root = child;
1319
1320 // Link n and child.
1321 child.right = node;
1322 node.parent = child;
1323 }
1324
1325 /**
1326 * Return the node following the given one, or nil if there isn't one.
1327 * Package visible for use by nested classes.
1328 *
1329 * @param node the current node, not nil
1330 * @return the next node in sorted order
1331 */
1332 final Node successor(Node node)
1333 {
1334 if (node.right != nil)
1335 {
1336 node = node.right;
1337 while (node.left != nil)
1338 node = node.left;
1339 return node;
1340 }
1341
1342 Node parent = node.parent;
1343 // Exploit fact that nil.right == nil and node is non-nil.
1344 while (node == parent.right)
1345 {
1346 node = parent;
1347 parent = parent.parent;
1348 }
1349 return parent;
1350 }
1351
1352 /**
1353 * Serializes this object to the given stream.
1354 *
1355 * @param s the stream to write to
1356 * @throws IOException if the underlying stream fails
1357 * @serialData the <i>size</i> (int), followed by key (Object) and value
1358 * (Object) pairs in sorted order
1359 */
1360 private void writeObject(ObjectOutputStream s) throws IOException
1361 {
1362 s.defaultWriteObject();
1363
1364 Node node = firstNode();
1365 s.writeInt(size);
1366 while (node != nil)
1367 {
1368 s.writeObject(node.key);
1369 s.writeObject(node.value);
1370 node = successor(node);
1371 }
1372 }
1373
1374 /**
1375 * Iterate over HashMap's entries. This implementation is parameterized
1376 * to give a sequential view of keys, values, or entries.
1377 *
1378 * @author Eric Blake <[email protected]>
1379 */
1380 private final class TreeIterator implements Iterator
1381 {
1382 /**
1383 * The type of this Iterator: {@link #KEYS}, {@link #VALUES},
1384 * or {@link #ENTRIES}.
1385 */
1386 private final int type;
1387 /** The number of modifications to the backing Map that we know about. */
1388 private int knownMod = modCount;
1389 /** The last Entry returned by a next() call. */
1390 private Node last;
1391 /** The next entry that should be returned by next(). */
1392 private Node next;
1393 /**
1394 * The last node visible to this iterator. This is used when iterating
1395 * on a SubMap.
1396 */
1397 private final Node max;
1398
1399 /**
1400 * Construct a new TreeIterator with the supplied type.
1401 * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
1402 */
1403 TreeIterator(int type)
1404 {
1405 // FIXME gcj cannot handle this. Bug java/4695
1406 // this(type, firstNode(), nil);
1407 this.type = type;
1408 this.next = firstNode();
1409 this.max = nil;
1410 }
1411
1412 /**
1413 * Construct a new TreeIterator with the supplied type. Iteration will
1414 * be from "first" (inclusive) to "max" (exclusive).
1415 *
1416 * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
1417 * @param first where to start iteration, nil for empty iterator
1418 * @param max the cutoff for iteration, nil for all remaining nodes
1419 */
1420 TreeIterator(int type, Node first, Node max)
1421 {
1422 this.type = type;
1423 this.next = first;
1424 this.max = max;
1425 }
1426
1427 /**
1428 * Returns true if the Iterator has more elements.
1429 * @return true if there are more elements
1430 * @throws ConcurrentModificationException if the TreeMap was modified
1431 */
1432 public boolean hasNext()
1433 {
1434 if (knownMod != modCount)
1435 throw new ConcurrentModificationException();
1436 return next != max;
1437 }
1438
1439 /**
1440 * Returns the next element in the Iterator's sequential view.
1441 * @return the next element
1442 * @throws ConcurrentModificationException if the TreeMap was modified
1443 * @throws NoSuchElementException if there is none
1444 */
1445 public Object next()
1446 {
1447 if (knownMod != modCount)
1448 throw new ConcurrentModificationException();
1449 if (next == max)
1450 throw new NoSuchElementException();
1451 last = next;
1452 next = successor(last);
1453
1454 if (type == VALUES)
1455 return last.value;
1456 else if (type == KEYS)
1457 return last.key;
1458 return last;
1459 }
1460
1461 /**
1462 * Removes from the backing TreeMap the last element which was fetched
1463 * with the <code>next()</code> method.
1464 * @throws ConcurrentModificationException if the TreeMap was modified
1465 * @throws IllegalStateException if called when there is no last element
1466 */
1467 public void remove()
1468 {
1469 if (knownMod != modCount)
1470 throw new ConcurrentModificationException();
1471 if (last == null)
1472 throw new IllegalStateException();
1473
1474 removeNode(last);
1475 last = null;
1476 knownMod++;
1477 }
1478 } // class TreeIterator
1479
1480 /**
1481 * Implementation of {@link #subMap(Object, Object)} and other map
1482 * ranges. This class provides a view of a portion of the original backing
1483 * map, and throws {@link IllegalArgumentException} for attempts to
1484 * access beyond that range.
1485 *
1486 * @author Eric Blake <[email protected]>
1487 */
1488 private final class SubMap extends AbstractMap implements SortedMap
1489 {
1490 /**
1491 * The lower range of this view, inclusive, or nil for unbounded.
1492 * Package visible for use by nested classes.
1493 */
1494 final Object minKey;
1495
1496 /**
1497 * The upper range of this view, exclusive, or nil for unbounded.
1498 * Package visible for use by nested classes.
1499 */
1500 final Object maxKey;
1501
1502 /**
1503 * The cache for {@link #entrySet()}.
1504 */
1505 private Set entries;
1506
1507 /**
1508 * Create a SubMap representing the elements between minKey (inclusive)
1509 * and maxKey (exclusive). If minKey is nil, SubMap has no lower bound
1510 * (headMap). If maxKey is nil, the SubMap has no upper bound (tailMap).
1511 *
1512 * @param minKey the lower bound
1513 * @param maxKey the upper bound
1514 * @throws IllegalArgumentException if minKey &gt; maxKey
1515 */
1516 SubMap(Object minKey, Object maxKey)
1517 {
1518 if (minKey != nil && maxKey != nil && compare(minKey, maxKey) > 0)
1519 throw new IllegalArgumentException("fromKey > toKey");
1520 this.minKey = minKey;
1521 this.maxKey = maxKey;
1522 }
1523
1524 /**
1525 * Check if "key" is in within the range bounds for this SubMap. The
1526 * lower ("from") SubMap range is inclusive, and the upper ("to") bound
1527 * is exclusive. Package visible for use by nested classes.
1528 *
1529 * @param key the key to check
1530 * @return true if the key is in range
1531 */
1532 final boolean keyInRange(Object key)
1533 {
1534 return ((minKey == nil || compare(key, minKey) >= 0)
1535 && (maxKey == nil || compare(key, maxKey) < 0));
1536 }
1537
1538 public void clear()
1539 {
1540 Node next = lowestGreaterThan(minKey, true);
1541 Node max = lowestGreaterThan(maxKey, false);
1542 while (next != max)
1543 {
1544 Node current = next;
1545 next = successor(current);
1546 removeNode(current);
1547 }
1548 }
1549
1550 public Comparator comparator()
1551 {
1552 return comparator;
1553 }
1554
1555 public boolean containsKey(Object key)
1556 {
1557 return keyInRange(key) && TreeMap.this.containsKey(key);
1558 }
1559
1560 public boolean containsValue(Object value)
1561 {
1562 Node node = lowestGreaterThan(minKey, true);
1563 Node max = lowestGreaterThan(maxKey, false);
1564 while (node != max)
1565 {
1566 if (equals(value, node.getValue()))
1567 return true;
1568 node = successor(node);
1569 }
1570 return false;
1571 }
1572
1573 public Set entrySet()
1574 {
1575 if (entries == null)
1576 // Create an AbstractSet with custom implementations of those methods
1577 // that can be overriden easily and efficiently.
1578 entries = new AbstractSet()
1579 {
1580 public int size()
1581 {
1582 return SubMap.this.size();
1583 }
1584
1585 public Iterator iterator()
1586 {
1587 Node first = lowestGreaterThan(minKey, true);
1588 Node max = lowestGreaterThan(maxKey, false);
1589 return new TreeIterator(ENTRIES, first, max);
1590 }
1591
1592 public void clear()
1593 {
1594 SubMap.this.clear();
1595 }
1596
1597 public boolean contains(Object o)
1598 {
1599 if (! (o instanceof Map.Entry))
1600 return false;
1601 Map.Entry me = (Map.Entry) o;
1602 Object key = me.getKey();
1603 if (! keyInRange(key))
1604 return false;
1605 Node n = getNode(key);
1606 return n != nil && AbstractSet.equals(me.getValue(), n.value);
1607 }
1608
1609 public boolean remove(Object o)
1610 {
1611 if (! (o instanceof Map.Entry))
1612 return false;
1613 Map.Entry me = (Map.Entry) o;
1614 Object key = me.getKey();
1615 if (! keyInRange(key))
1616 return false;
1617 Node n = getNode(key);
1618 if (n != nil && AbstractSet.equals(me.getValue(), n.value))
1619 {
1620 removeNode(n);
1621 return true;
1622 }
1623 return false;
1624 }
1625 };
1626 return entries;
1627 }
1628
1629 public Object firstKey()
1630 {
1631 Node node = lowestGreaterThan(minKey, true);
1632 if (node == nil || ! keyInRange(node.key))
1633 throw new NoSuchElementException();
1634 return node.key;
1635 }
1636
1637 public Object get(Object key)
1638 {
1639 if (keyInRange(key))
1640 return TreeMap.this.get(key);
1641 return null;
1642 }
1643
1644 public SortedMap headMap(Object toKey)
1645 {
1646 if (! keyInRange(toKey))
1647 throw new IllegalArgumentException("key outside range");
1648 return new SubMap(minKey, toKey);
1649 }
1650
1651 public Set keySet()
1652 {
1653 if (this.keys == null)
1654 // Create an AbstractSet with custom implementations of those methods
1655 // that can be overriden easily and efficiently.
1656 this.keys = new AbstractSet()
1657 {
1658 public int size()
1659 {
1660 return SubMap.this.size();
1661 }
1662
1663 public Iterator iterator()
1664 {
1665 Node first = lowestGreaterThan(minKey, true);
1666 Node max = lowestGreaterThan(maxKey, false);
1667 return new TreeIterator(KEYS, first, max);
1668 }
1669
1670 public void clear()
1671 {
1672 SubMap.this.clear();
1673 }
1674
1675 public boolean contains(Object o)
1676 {
1677 if (! keyInRange(o))
1678 return false;
1679 return getNode(o) != nil;
1680 }
1681
1682 public boolean remove(Object o)
1683 {
1684 if (! keyInRange(o))
1685 return false;
1686 Node n = getNode(o);
1687 if (n != nil)
1688 {
1689 removeNode(n);
1690 return true;
1691 }
1692 return false;
1693 }
1694 };
1695 return this.keys;
1696 }
1697
1698 public Object lastKey()
1699 {
1700 Node node = highestLessThan(maxKey);
1701 if (node == nil || ! keyInRange(node.key))
1702 throw new NoSuchElementException();
1703 return node.key;
1704 }
1705
1706 public Object put(Object key, Object value)
1707 {
1708 if (! keyInRange(key))
1709 throw new IllegalArgumentException("Key outside range");
1710 return TreeMap.this.put(key, value);
1711 }
1712
1713 public Object remove(Object key)
1714 {
1715 if (keyInRange(key))
1716 return TreeMap.this.remove(key);
1717 return null;
1718 }
1719
1720 public int size()
1721 {
1722 Node node = lowestGreaterThan(minKey, true);
1723 Node max = lowestGreaterThan(maxKey, false);
1724 int count = 0;
1725 while (node != max)
1726 {
1727 count++;
1728 node = successor(node);
1729 }
1730 return count;
1731 }
1732
1733 public SortedMap subMap(Object fromKey, Object toKey)
1734 {
1735 if (! keyInRange(fromKey) || ! keyInRange(toKey))
1736 throw new IllegalArgumentException("key outside range");
1737 return new SubMap(fromKey, toKey);
1738 }
1739
1740 public SortedMap tailMap(Object fromKey)
1741 {
1742 if (! keyInRange(fromKey))
1743 throw new IllegalArgumentException("key outside range");
1744 return new SubMap(fromKey, maxKey);
1745 }
1746
1747 public Collection values()
1748 {
1749 if (this.values == null)
1750 // Create an AbstractCollection with custom implementations of those
1751 // methods that can be overriden easily and efficiently.
1752 this.values = new AbstractCollection()
1753 {
1754 public int size()
1755 {
1756 return SubMap.this.size();
1757 }
1758
1759 public Iterator iterator()
1760 {
1761 Node first = lowestGreaterThan(minKey, true);
1762 Node max = lowestGreaterThan(maxKey, false);
1763 return new TreeIterator(VALUES, first, max);
1764 }
1765
1766 public void clear()
1767 {
1768 SubMap.this.clear();
1769 }
1770 };
1771 return this.keys;
1772 }
1773 } // class SubMap
1774} // class TreeMap
Note: See TracBrowser for help on using the repository browser.