/[classpath]/classpath/java/util/TreeMap.java
ViewVC logotype

Diff of /classpath/java/util/TreeMap.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.1.13  
changed lines
  Added in v.1.14

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26