/* TreeMap.java -- a class providing a basic Red-Black Tree data structure,
   mapping Object --> Object
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.util;

import gnu.java.lang.CPStringBuilder;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * This class provides a red-black tree implementation of the SortedMap
 * interface.  Elements in the Map will be sorted by either a user-provided
 * Comparator object, or by the natural ordering of the keys.
 *
 * The algorithms are adopted from Corman, Leiserson, and Rivest's
 * <i>Introduction to Algorithms.</i>  TreeMap guarantees O(log n)
 * insertion and deletion of elements.  That 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. If something is already sorted, you may want to
 * just use a LinkedHashMap to maintain the order while providing O(1) access.
 *
 * TreeMap is a part of the JDK1.2 Collections API.  Null keys are allowed
 * only if a Comparator is used which can deal with them; natural ordering
 * cannot cope with null.  Null values are always allowed. Note that the
 * ordering must be <i>consistent with equals</i> to correctly implement
 * the Map interface. If this condition is violated, the map is still
 * well-behaved, but you may have suprising results when comparing it to
 * other maps.<p>
 *
 * This implementation is not synchronized. If you need to share this between
 * multiple threads, do something like:<br>
 * <code>SortedMap m
 *       = Collections.synchronizedSortedMap(new TreeMap(...));</code><p>
 *
 * The iterators are <i>fail-fast</i>, meaning that any structural
 * modification, except for <code>remove()</code> called on the iterator
 * itself, cause the iterator to throw a
 * <code>ConcurrentModificationException</code> rather than exhibit
 * non-deterministic behavior.
 *
 * @author Jon Zeppieri
 * @author Bryce McKinlay
 * @author Eric Blake (ebb9@email.byu.edu)
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 * @see Map
 * @see HashMap
 * @see Hashtable
 * @see LinkedHashMap
 * @see Comparable
 * @see Comparator
 * @see Collection
 * @see Collections#synchronizedSortedMap(SortedMap)
 * @since 1.2
 * @status updated to 1.6
 */
public class TreeMap<K, V> extends AbstractMap<K, V>
  implements NavigableMap<K, V>, Cloneable, Serializable
{
  // Implementation note:
  // A red-black tree is a binary search tree with the additional properties
  // that all paths to a leaf node visit the same number of black nodes,
  // and no red node has red children. To avoid some null-pointer checks,
  // we use the special node nil which is always black, has no relatives,
  // and has key and value of null (but is not equal to a mapping of null).

  /**
   * Compatible with JDK 1.2.
   */
  private static final long serialVersionUID = 919286545866124006L;

  /**
   * Color status of a node. Package visible for use by nested classes.
   */
  static final int RED = -1,
                   BLACK = 1;

  /**
   * Sentinal node, used to avoid null checks for corner cases and make the
   * delete rebalance code simpler. The rebalance code must never assign
   * the parent, left, or right of nil, but may safely reassign the color
   * to be black. This object must never be used as a key in a TreeMap, or
   * it will break bounds checking of a SubMap.
   */
  static final Node nil = new Node(null, null, BLACK);
  static
    {
      // Nil is self-referential, so we must initialize it after creation.
      nil.parent = nil;
      nil.left = nil;
      nil.right = nil;
    }

  /**
   * The root node of this TreeMap.
   */
  private transient Node root;

  /**
   * The size of this TreeMap. Package visible for use by nested classes.
   */
  transient int size;

  /**
   * The cache for {@link #entrySet()}.
   */
  private transient Set<Map.Entry<K,V>> entries;

  /**
   * The cache for {@link #descendingMap()}.
   */
  private transient NavigableMap<K,V> descendingMap;

  /**
   * The cache for {@link #navigableKeySet()}.
   */
  private transient NavigableSet<K> nKeys;

  /**
   * Counts the number of modifications this TreeMap has undergone, used
   * by Iterators to know when to throw ConcurrentModificationExceptions.
   * Package visible for use by nested classes.
   */
  transient int modCount;

  /**
   * This TreeMap's comparator, or null for natural ordering.
   * Package visible for use by nested classes.
   * @serial the comparator ordering this tree, or null
   */
  final Comparator<? super K> comparator;

  /**
   * Class to represent an entry in the tree. Holds a single key-value pair,
   * plus pointers to parent and child nodes.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class Node<K, V> extends AbstractMap.SimpleEntry<K, V>
  {
    // All fields package visible for use by nested classes.
    /** The color of this node. */
    int color;

    /** The left child node. */
    Node<K, V> left = nil;
    /** The right child node. */
    Node<K, V> right = nil;
    /** The parent node. */
    Node<K, V> parent = nil;

    /**
     * Simple constructor.
     * @param key the key
     * @param value the value
     */
    Node(K key, V value, int color)
    {
      super(key, value);
      this.color = color;
    }
  }

  /**
   * Instantiate a new TreeMap with no elements, using the keys' natural
   * ordering to sort. All entries in the map must have a key which implements
   * Comparable, and which are <i>mutually comparable</i>, otherwise map
   * operations may throw a {@link ClassCastException}. Attempts to use
   * a null key will throw a {@link NullPointerException}.
   *
   * @see Comparable
   */
  public TreeMap()
  {
    this((Comparator) null);
  }

  /**
   * Instantiate a new TreeMap with no elements, using the provided comparator
   * to sort. All entries in the map must have keys which are mutually
   * comparable by the Comparator, otherwise map operations may throw a
   * {@link ClassCastException}.
   *
   * @param c the sort order for the keys of this map, or null
   *        for the natural order
   */
  public TreeMap(Comparator<? super K> c)
  {
    comparator = c;
    fabricateTree(0);
  }

  /**
   * Instantiate a new TreeMap, initializing it with all of the elements in
   * the provided Map.  The elements will be sorted using the natural
   * ordering of the keys. This algorithm runs in n*log(n) time. All entries
   * in the map must have keys which implement Comparable and are mutually
   * comparable, otherwise map operations may throw a
   * {@link ClassCastException}.
   *
   * @param map a Map, whose entries will be put into this TreeMap
   * @throws ClassCastException if the keys in the provided Map are not
   *         comparable
   * @throws NullPointerException if map is null
   * @see Comparable
   */
  public TreeMap(Map<? extends K, ? extends V> map)
  {
    this((Comparator) null);
    putAll(map);
  }

  /**
   * Instantiate a new TreeMap, initializing it with all of the elements in
   * the provided SortedMap.  The elements will be sorted using the same
   * comparator as in the provided SortedMap. This runs in linear time.
   *
   * @param sm a SortedMap, whose entries will be put into this TreeMap
   * @throws NullPointerException if sm is null
   */
  public TreeMap(SortedMap<K, ? extends V> sm)
  {
    this(sm.comparator());
    int pos = sm.size();
    Iterator itr = sm.entrySet().iterator();

    fabricateTree(pos);
    Node node = firstNode();

    while (--pos >= 0)
      {
        Map.Entry me = (Map.Entry) itr.next();
        node.key = me.getKey();
        node.value = me.getValue();
        node = successor(node);
      }
  }

  /**
   * Clears the Map so it has no keys. This is O(1).
   */
  public void clear()
  {
    if (size > 0)
      {
        modCount++;
        root = nil;
        size = 0;
      }
  }

  /**
   * Returns a shallow clone of this TreeMap. The Map itself is cloned,
   * but its contents are not.
   *
   * @return the clone
   */
  public Object clone()
  {
    TreeMap copy = null;
    try
      {
        copy = (TreeMap) super.clone();
      }
    catch (CloneNotSupportedException x)
      {
      }
    copy.entries = null;
    copy.fabricateTree(size);

    Node node = firstNode();
    Node cnode = copy.firstNode();

    while (node != nil)
      {
        cnode.key = node.key;
        cnode.value = node.value;
        node = successor(node);
        cnode = copy.successor(cnode);
      }
    return copy;
  }

  /**
   * Return the comparator used to sort this map, or null if it is by
   * natural order.
   *
   * @return the map's comparator
   */
  public Comparator<? super K> comparator()
  {
    return comparator;
  }

  /**
   * Returns true if the map contains a mapping for the given key.
   *
   * @param key the key to look for
   * @return true if the key has a mapping
   * @throws ClassCastException if key is not comparable to map elements
   * @throws NullPointerException if key is null and the comparator is not
   *         tolerant of nulls
   */
  public boolean containsKey(Object key)
  {
    return getNode((K) key) != nil;
  }

  /**
   * Returns true if the map contains at least one mapping to the given value.
   * This requires linear time.
   *
   * @param value the value to look for
   * @return true if the value appears in a mapping
   */
  public boolean containsValue(Object value)
  {
    Node node = firstNode();
    while (node != nil)
      {
        if (equals(value, node.value))
          return true;
        node = successor(node);
      }
    return false;
  }

  /**
   * Returns a "set view" of this TreeMap's entries. The set is backed by
   * the TreeMap, so changes in one show up in the other.  The set supports
   * element removal, but not element addition.<p>
   *
   * Note that the iterators for all three views, from keySet(), entrySet(),
   * and values(), traverse the TreeMap in sorted sequence.
   *
   * @return a set view of the entries
   * @see #keySet()
   * @see #values()
   * @see Map.Entry
   */
  public Set<Map.Entry<K,V>> entrySet()
  {
    if (entries == null)
      // Create an AbstractSet with custom implementations of those methods
      // that can be overriden easily and efficiently.
      entries = new NavigableEntrySet();
    return entries;
  }

  /**
   * Returns the first (lowest) key in the map.
   *
   * @return the first key
   * @throws NoSuchElementException if the map is empty
   */
  public K firstKey()
  {
    if (root == nil)
      throw new NoSuchElementException();
    return firstNode().key;
  }

  /**
   * Return the value in this TreeMap associated with the supplied key,
   * or <code>null</code> if the key maps to nothing.  NOTE: Since the value
   * could also be null, you must use containsKey to see if this key
   * actually maps to something.
   *
   * @param key the key for which to fetch an associated value
   * @return what the key maps to, if present
   * @throws ClassCastException if key is not comparable to elements in the map
   * @throws NullPointerException if key is null but the comparator does not
   *         tolerate nulls
   * @see #put(Object, Object)
   * @see #containsKey(Object)
   */
  public V get(Object key)
  {
    // Exploit fact that nil.value == null.
    return getNode((K) key).value;
  }

  /**
   * Returns a view of this Map including all entries with keys less than
   * <code>toKey</code>. The returned map is backed by the original, so changes
   * in one appear in the other. The submap will throw an
   * {@link IllegalArgumentException} for any attempt to access or add an
   * element beyond the specified cutoff. The returned map does not include
   * the endpoint; if you want inclusion, pass the successor element
   * or call <code>headMap(toKey, true)</code>.  This is equivalent to
   * calling <code>headMap(toKey, false)</code>.
   *
   * @param toKey the (exclusive) cutoff point
   * @return a view of the map less than the cutoff
   * @throws ClassCastException if <code>toKey</code> is not compatible with
   *         the comparator (or is not Comparable, for natural ordering)
   * @throws NullPointerException if toKey is null, but the comparator does not
   *         tolerate null elements
   */
  public SortedMap<K, V> headMap(K toKey)
  {
    return headMap(toKey, false);
  }

  /**
   * Returns a view of this Map including all entries with keys less than
   * (or equal to, if <code>inclusive</code> is true) <code>toKey</code>.
   * The returned map is backed by the original, so changes in one appear
   * in the other. The submap will throw an {@link IllegalArgumentException}
   * for any attempt to access or add an element beyond the specified cutoff.
   *
   * @param toKey the cutoff point
   * @param inclusive true if the cutoff point should be included.
   * @return a view of the map less than (or equal to, if <code>inclusive</code>
   *         is true) the cutoff.
   * @throws ClassCastException if <code>toKey</code> is not compatible with
   *         the comparator (or is not Comparable, for natural ordering)
   * @throws NullPointerException if toKey is null, but the comparator does not
   *         tolerate null elements
   */
  public NavigableMap<K, V> headMap(K toKey, boolean inclusive)
  {
    return new SubMap((K)(Object)nil, inclusive
                      ? successor(getNode(toKey)).key : toKey);
  }

  /**
   * Returns a "set view" of this TreeMap's keys. The set is backed by the
   * TreeMap, so changes in one show up in the other.  The set supports
   * element removal, but not element addition.
   *
   * @return a set view of the keys
   * @see #values()
   * @see #entrySet()
   */
  public Set<K> keySet()
  {
    if (keys == null)
      // Create an AbstractSet with custom implementations of those methods
      // that can be overriden easily and efficiently.
      keys = new KeySet();
    return keys;
  }

  /**
   * Returns the last (highest) key in the map.
   *
   * @return the last key
   * @throws NoSuchElementException if the map is empty
   */
  public K lastKey()
  {
    if (root == nil)
      throw new NoSuchElementException("empty");
    return lastNode().key;
  }

  /**
   * Puts the supplied value into the Map, mapped by the supplied key.
   * The value may be retrieved by any object which <code>equals()</code>
   * this key. NOTE: Since the prior value could also be null, you must
   * first use containsKey if you want to see if you are replacing the
   * key's mapping.
   *
   * @param key the key used to locate the value
   * @param value the value to be stored in the Map
   * @return the prior mapping of the key, or null if there was none
   * @throws ClassCastException if key is not comparable to current map keys
   * @throws NullPointerException if key is null, but the comparator does
   *         not tolerate nulls
   * @see #get(Object)
   * @see Object#equals(Object)
   */
  public V put(K key, V value)
  {
    Node<K,V> current = root;
    Node<K,V> parent = nil;
    int comparison = 0;

    // Find new node's parent.
    while (current != nil)
      {
        parent = current;
        comparison = compare(key, current.key);
        if (comparison > 0)
          current = current.right;
        else if (comparison < 0)
          current = current.left;
        else // Key already in tree.
          return current.setValue(value);
      }

    // Set up new node.
    Node n = new Node(key, value, RED);
    n.parent = parent;

    // Insert node in tree.
    modCount++;
    size++;
    if (parent == nil)
      {
        // Special case inserting into an empty tree.
        root = n;
        return null;
      }
    if (comparison > 0)
      parent.right = n;
    else
      parent.left = n;

    // Rebalance after insert.
    insertFixup(n);
    return null;
  }

  /**
   * Copies all elements of the given map into this TreeMap.  If this map
   * already has a mapping for a key, the new mapping replaces the current
   * one.
   *
   * @param m the map to be added
   * @throws ClassCastException if a key in m is not comparable with keys
   *         in the map
   * @throws NullPointerException if a key in m is null, and the comparator
   *         does not tolerate nulls
   */
  public void putAll(Map<? extends K, ? extends V> m)
  {
    Iterator itr = m.entrySet().iterator();
    int pos = m.size();
    while (--pos >= 0)
      {
        Map.Entry<K,V> e = (Map.Entry<K,V>) itr.next();
        put(e.getKey(), e.getValue());
      }
  }

  /**
   * Removes from the TreeMap and returns the value which is mapped by the
   * supplied key. If the key maps to nothing, then the TreeMap remains
   * unchanged, and <code>null</code> is returned. NOTE: Since the value
   * could also be null, you must use containsKey to see if you are
   * actually removing a mapping.
   *
   * @param key the key used to locate the value to remove
   * @return whatever the key mapped to, if present
   * @throws ClassCastException if key is not comparable to current map keys
   * @throws NullPointerException if key is null, but the comparator does
   *         not tolerate nulls
   */
  public V remove(Object key)
  {
    Node<K, V> n = getNode((K)key);
    if (n == nil)
      return null;
    // Note: removeNode can alter the contents of n, so save value now.
    V result = n.value;
    removeNode(n);
    return result;
  }

  /**
   * Returns the number of key-value mappings currently in this Map.
   *
   * @return the size
   */
  public int size()
  {
    return size;
  }

  /**
   * Returns a view of this Map including all entries with keys greater or
   * equal to <code>fromKey</code> and less than <code>toKey</code> (a
   * half-open interval). The returned map is backed by the original, so
   * changes in one appear in the other. The submap will throw an
   * {@link IllegalArgumentException} for any attempt to access or add an
   * element beyond the specified cutoffs. The returned map includes the low
   * endpoint but not the high; if you want to reverse this behavior on
   * either end, pass in the successor element or call
   * {@link #subMap(K,boolean,K,boolean)}.  This call is equivalent to
   * <code>subMap(fromKey, true, toKey, false)</code>.
   *
   * @param fromKey the (inclusive) low cutoff point
   * @param toKey the (exclusive) high cutoff point
   * @return a view of the map between the cutoffs
   * @throws ClassCastException if either cutoff is not compatible with
   *         the comparator (or is not Comparable, for natural ordering)
   * @throws NullPointerException if fromKey or toKey is null, but the
   *         comparator does not tolerate null elements
   * @throws IllegalArgumentException if fromKey is greater than toKey
   */
  public SortedMap<K, V> subMap(K fromKey, K toKey)
  {
    return subMap(fromKey, true, toKey, false);
  }

  /**
   * Returns a view of this Map including all entries with keys greater (or
   * equal to, if <code>fromInclusive</code> is true) <code>fromKey</code> and
   * less than (or equal to, if <code>toInclusive</code> is true)
   * <code>toKey</code>. The returned map is backed by the original, so
   * changes in one appear in the other. The submap will throw an
   * {@link IllegalArgumentException} for any attempt to access or add an
   * element beyond the specified cutoffs.
   *
   * @param fromKey the low cutoff point
   * @param fromInclusive true if the low cutoff point should be included.
   * @param toKey the high cutoff point
   * @param toInclusive true if the high cutoff point should be included.
   * @return a view of the map for the specified range.
   * @throws ClassCastException if either cutoff is not compatible with
   *         the comparator (or is not Comparable, for natural ordering)
   * @throws NullPointerException if fromKey or toKey is null, but the
   *         comparator does not tolerate null elements
   * @throws IllegalArgumentException if fromKey is greater than toKey
   */
  public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive,
                                   K toKey, boolean toInclusive)
  {
    return new SubMap(fromInclusive ? fromKey : successor(getNode(fromKey)).key,
                      toInclusive ? successor(getNode(toKey)).key : toKey);
  }

  /**
   * Returns a view of this Map including all entries with keys greater or
   * equal to <code>fromKey</code>. The returned map is backed by the
   * original, so changes in one appear in the other. The submap will throw an
   * {@link IllegalArgumentException} for any attempt to access or add an
   * element beyond the specified cutoff. The returned map includes the
   * endpoint; if you want to exclude it, pass in the successor element.
   * This is equivalent to calling <code>tailMap(fromKey, true)</code>.
   *
   * @param fromKey the (inclusive) low cutoff point
   * @return a view of the map above the cutoff
   * @throws ClassCastException if <code>fromKey</code> is not compatible with
   *         the comparator (or is not Comparable, for natural ordering)
   * @throws NullPointerException if fromKey is null, but the comparator
   *         does not tolerate null elements
   */
  public SortedMap<K, V> tailMap(K fromKey)
  {
    return tailMap(fromKey, true);
  }

  /**
   * Returns a view of this Map including all entries with keys greater or
   * equal to <code>fromKey</code>. The returned map is backed by the
   * original, so changes in one appear in the other. The submap will throw an
   * {@link IllegalArgumentException} for any attempt to access or add an
   * element beyond the specified cutoff. The returned map includes the
   * endpoint; if you want to exclude it, pass in the successor element.
   *
   * @param fromKey the low cutoff point
   * @param inclusive true if the cutoff point should be included.
   * @return a view of the map above the cutoff
   * @throws ClassCastException if <code>fromKey</code> is not compatible with
   *         the comparator (or is not Comparable, for natural ordering)
   * @throws NullPointerException if fromKey is null, but the comparator
   *         does not tolerate null elements
   */
  public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive)
  {
    return new SubMap(inclusive ? fromKey : successor(getNode(fromKey)).key,
                      (K)(Object)nil);
  }

  /**
   * Returns a "collection view" (or "bag view") of this TreeMap's values.
   * The collection is backed by the TreeMap, so changes in one show up
   * in the other.  The collection supports element removal, but not element
   * addition.
   *
   * @return a bag view of the values
   * @see #keySet()
   * @see #entrySet()
   */
  public Collection<V> values()
  {
    if (values == null)
      // We don't bother overriding many of the optional methods, as doing so
      // wouldn't provide any significant performance advantage.
      values = new AbstractCollection<V>()
      {
        public int size()
        {
          return size;
        }

        public Iterator<V> iterator()
        {
          return new TreeIterator(VALUES);
        }

        public void clear()
        {
          TreeMap.this.clear();
        }
      };
    return values;
  }

  /**
   * Compares two elements by the set comparator, or by natural ordering.
   * Package visible for use by nested classes.
   *
   * @param o1 the first object
   * @param o2 the second object
   * @throws ClassCastException if o1 and o2 are not mutually comparable,
   *         or are not Comparable with natural ordering
   * @throws NullPointerException if o1 or o2 is null with natural ordering
   */
  final int compare(K o1, K o2)
  {
    return (comparator == null
            ? ((Comparable) o1).compareTo(o2)
            : comparator.compare(o1, o2));
  }

  /**
   * Maintain red-black balance after deleting a node.
   *
   * @param node the child of the node just deleted, possibly nil
   * @param parent the parent of the node just deleted, never nil
   */
  private void deleteFixup(Node<K,V> node, Node<K,V> parent)
  {
    // if (parent == nil)
    //   throw new InternalError();
    // If a black node has been removed, we need to rebalance to avoid
    // violating the "same number of black nodes on any path" rule. If
    // node is red, we can simply recolor it black and all is well.
    while (node != root && node.color == BLACK)
      {
        if (node == parent.left)
          {
            // Rebalance left side.
            Node<K,V> sibling = parent.right;
            // if (sibling == nil)
            //   throw new InternalError();
            if (sibling.color == RED)
              {
                // Case 1: Sibling is red.
                // Recolor sibling and parent, and rotate parent left.
                sibling.color = BLACK;
                parent.color = RED;
                rotateLeft(parent);
                sibling = parent.right;
              }

            if (sibling.left.color == BLACK && sibling.right.color == BLACK)
              {
                // Case 2: Sibling has no red children.
                // Recolor sibling, and move to parent.
                sibling.color = RED;
                node = parent;
                parent = parent.parent;
              }
            else
              {
                if (sibling.right.color == BLACK)
                  {
                    // Case 3: Sibling has red left child.
                    // Recolor sibling and left child, rotate sibling right.
                    sibling.left.color = BLACK;
                    sibling.color = RED;
                    rotateRight(sibling);
                    sibling = parent.right;
                  }
                // Case 4: Sibling has red right child. Recolor sibling,
                // right child, and parent, and rotate parent left.
                sibling.color = parent.color;
                parent.color = BLACK;
                sibling.right.color = BLACK;
                rotateLeft(parent);
                node = root; // Finished.
              }
          }
        else
          {
            // Symmetric "mirror" of left-side case.
            Node<K,V> sibling = parent.left;
            // if (sibling == nil)
            //   throw new InternalError();
            if (sibling.color == RED)
              {
                // Case 1: Sibling is red.
                // Recolor sibling and parent, and rotate parent right.
                sibling.color = BLACK;
                parent.color = RED;
                rotateRight(parent);
                sibling = parent.left;
              }

            if (sibling.right.color == BLACK && sibling.left.color == BLACK)
              {
                // Case 2: Sibling has no red children.
                // Recolor sibling, and move to parent.
                sibling.color = RED;
                node = parent;
                parent = parent.parent;
              }
            else
              {
                if (sibling.left.color == BLACK)
                  {
                    // Case 3: Sibling has red right child.
                    // Recolor sibling and right child, rotate sibling left.
                    sibling.right.color = BLACK;
                    sibling.color = RED;
                    rotateLeft(sibling);
                    sibling = parent.left;
                  }
                // Case 4: Sibling has red left child. Recolor sibling,
                // left child, and parent, and rotate parent right.
                sibling.color = parent.color;
                parent.color = BLACK;
                sibling.left.color = BLACK;
                rotateRight(parent);
                node = root; // Finished.
              }
          }
      }
    node.color = BLACK;
  }

  /**
   * Construct a perfectly balanced tree consisting of n "blank" nodes. This
   * permits a tree to be generated from pre-sorted input in linear time.
   *
   * @param count the number of blank nodes, non-negative
   */
  private void fabricateTree(final int count)
  {
    if (count == 0)
      {
        root = nil;
        size = 0;
        return;
      }

    // We color every row of nodes black, except for the overflow nodes.
    // I believe that this is the optimal arrangement. We construct the tree
    // in place by temporarily linking each node to the next node in the row,
    // then updating those links to the children when working on the next row.

    // Make the root node.
    root = new Node(null, null, BLACK);
    size = count;
    Node row = root;
    int rowsize;

    // Fill each row that is completely full of nodes.
    for (rowsize = 2; rowsize + rowsize <= count; rowsize <<= 1)
      {
        Node parent = row;
        Node last = null;
        for (int i = 0; i < rowsize; i += 2)
          {
            Node left = new Node(null, null, BLACK);
            Node right = new Node(null, null, BLACK);
            left.parent = parent;
            left.right = right;
            right.parent = parent;
            parent.left = left;
            Node next = parent.right;
            parent.right = right;
            parent = next;
            if (last != null)
              last.right = left;
            last = right;
          }
        row = row.left;
      }

    // Now do the partial final row in red.
    int overflow = count - rowsize;
    Node parent = row;
    int i;
    for (i = 0; i < overflow; i += 2)
      {
        Node left = new Node(null, null, RED);
        Node right = new Node(null, null, RED);
        left.parent = parent;
        right.parent = parent;
        parent.left = left;
        Node next = parent.right;
        parent.right = right;
        parent = next;
      }
    // Add a lone left node if necessary.
    if (i - overflow == 0)
      {
        Node left = new Node(null, null, RED);
        left.parent = parent;
        parent.left = left;
        parent = parent.right;
        left.parent.right = nil;
      }
    // Unlink the remaining nodes of the previous row.
    while (parent != nil)
      {
        Node next = parent.right;
        parent.right = nil;
        parent = next;
      }
  }

  /**
   * Returns the first sorted node in the map, or nil if empty. Package
   * visible for use by nested classes.
   *
   * @return the first node
   */
  final Node<K, V> firstNode()
  {
    // Exploit fact that nil.left == nil.
    Node node = root;
    while (node.left != nil)
      node = node.left;
    return node;
  }

  /**
   * Return the TreeMap.Node associated with key, or the nil node if no such
   * node exists in the tree. Package visible for use by nested classes.
   *
   * @param key the key to search for
   * @return the node where the key is found, or nil
   */
  final Node<K, V> getNode(K key)
  {
    Node<K,V> current = root;
    while (current != nil)
      {
        int comparison = compare(key, current.key);
        if (comparison > 0)
          current = current.right;
        else if (comparison < 0)
          current = current.left;
        else
          return current;
      }
    return current;
  }

  /**
   * Find the "highest" node which is &lt; key. If key is nil, return last
   * node. Package visible for use by nested classes.
   *
   * @param key the upper bound, exclusive
   * @return the previous node
   */
  final Node<K,V> highestLessThan(K key)
  {
    return highestLessThan(key, false);
  }

  /**
   * Find the "highest" node which is &lt; (or equal to,
   * if <code>equal</code> is true) key. If key is nil,
   * return last node. Package visible for use by nested
   * classes.
   *
   * @param key the upper bound, exclusive
   * @param equal true if the key should be returned if found.
   * @return the previous node
   */
  final Node<K,V> highestLessThan(K key, boolean equal)
  {
    if (key == nil)
      return lastNode();

    Node<K,V> last = nil;
    Node<K,V> current = root;
    int comparison = 0;

    while (current != nil)
      {
        last = current;
        comparison = compare(key, current.key);
        if (comparison > 0)
          current = current.right;
        else if (comparison < 0)
          current = current.left;
        else // Exact match.
          return (equal ? last : predecessor(last));
      }
    return comparison < 0 ? predecessor(last) : last;
  }

  /**
   * Maintain red-black balance after inserting a new node.
   *
   * @param n the newly inserted node
   */
  private void insertFixup(Node<K,V> n)
  {
    // Only need to rebalance when parent is a RED node, and while at least
    // 2 levels deep into the tree (ie: node has a grandparent). Remember
    // that nil.color == BLACK.
    while (n.parent.color == RED && n.parent.parent != nil)
      {
        if (n.parent == n.parent.parent.left)
          {
            Node uncle = n.parent.parent.right;
            // Uncle may be nil, in which case it is BLACK.
            if (uncle.color == RED)
              {
                // Case 1. Uncle is RED: Change colors of parent, uncle,
                // and grandparent, and move n to grandparent.
                n.parent.color = BLACK;
                uncle.color = BLACK;
                uncle.parent.color = RED;
                n = uncle.parent;
              }
            else
              {
                if (n == n.parent.right)
                  {
                    // Case 2. Uncle is BLACK and x is right child.
                    // Move n to parent, and rotate n left.
                    n = n.parent;
                    rotateLeft(n);
                  }
                // Case 3. Uncle is BLACK and x is left child.
                // Recolor parent, grandparent, and rotate grandparent right.
                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;
            // Uncle may be nil, in which case it is BLACK.
            if (uncle.color == RED)
              {
                // Case 1. Uncle is RED: Change colors of parent, uncle,
                // and grandparent, and move n to grandparent.
                n.parent.color = BLACK;
                uncle.color = BLACK;
                uncle.parent.color = RED;
                n = uncle.parent;
              }
            else
              {
                if (n == n.parent.left)
                {
                    // Case 2. Uncle is BLACK and x is left child.
                    // Move n to parent, and rotate n right.
                    n = n.parent;
                    rotateRight(n);
                  }
                // Case 3. Uncle is BLACK and x is right child.
                // Recolor parent, grandparent, and rotate grandparent left.
                n.parent.color = BLACK;
                n.parent.parent.color = RED;
                rotateLeft(n.parent.parent);
              }
          }
      }
    root.color = BLACK;
  }

  /**
   * Returns the last sorted node in the map, or nil if empty.
   *
   * @return the last node
   */
  private Node<K,V> lastNode()
  {
    // Exploit fact that nil.right == nil.
    Node node = root;
    while (node.right != nil)
      node = node.right;
    return node;
  }

  /**
   * Find the "lowest" node which is &gt;= key. If key is nil, return either
   * nil or the first node, depending on the parameter first.  Package visible
   * for use by nested classes.
   *
   * @param key the lower bound, inclusive
   * @param first true to return the first element instead of nil for nil key
   * @return the next node
   */
  final Node<K,V> lowestGreaterThan(K key, boolean first)
  {
    return lowestGreaterThan(key, first, true);
  }

  /**
   * Find the "lowest" node which is &gt; (or equal to, if <code>equal</code>
   * is true) key. If key is nil, return either nil or the first node, depending
   * on the parameter first.  Package visible for use by nested classes.
   *
   * @param key the lower bound, inclusive
   * @param first true to return the first element instead of nil for nil key
   * @param equal true if the key should be returned if found.
   * @return the next node
   */
  final Node<K,V> lowestGreaterThan(K key, boolean first, boolean equal)
  {
    if (key == nil)
      return first ? firstNode() : nil;

    Node<K,V> last = nil;
    Node<K,V> current = root;
    int comparison = 0;

    while (current != nil)
      {
        last = current;
        comparison = compare(key, current.key);
        if (comparison > 0)
          current = current.right;
        else if (comparison < 0)
          current = current.left;
        else
          return (equal ? current : successor(current));
      }
    return comparison > 0 ? successor(last) : last;
  }

  /**
   * Return the node preceding the given one, or nil if there isn't one.
   *
   * @param node the current node, not nil
   * @return the prior node in sorted order
   */
  private Node<K,V> predecessor(Node<K,V> node)
  {
    if (node.left != nil)
      {
        node = node.left;
        while (node.right != nil)
          node = node.right;
        return node;
      }

    Node parent = node.parent;
    // Exploit fact that nil.left == nil and node is non-nil.
    while (node == parent.left)
      {
        node = parent;
        parent = node.parent;
      }
    return parent;
  }

  /**
   * Construct a tree from sorted keys in linear time. Package visible for
   * use by TreeSet.
   *
   * @param s the stream to read from
   * @param count the number of keys to read
   * @param readValues true to read values, false to insert "" as the value
   * @throws ClassNotFoundException if the underlying stream fails
   * @throws IOException if the underlying stream fails
   * @see #readObject(ObjectInputStream)
   * @see TreeSet#readObject(ObjectInputStream)
   */
  final void putFromObjStream(ObjectInputStream s, int count,
                              boolean readValues)
    throws IOException, ClassNotFoundException
  {
    fabricateTree(count);
    Node node = firstNode();

    while (--count >= 0)
      {
        node.key = s.readObject();
        node.value = readValues ? s.readObject() : "";
        node = successor(node);
      }
  }

  /**
   * Construct a tree from sorted keys in linear time, with values of "".
   * Package visible for use by TreeSet, which uses a value type of String.
   *
   * @param keys the iterator over the sorted keys
   * @param count the number of nodes to insert
   * @see TreeSet#TreeSet(SortedSet)
   */
  final void putKeysLinear(Iterator<K> keys, int count)
  {
    fabricateTree(count);
    Node<K,V> node = firstNode();

    while (--count >= 0)
      {
        node.key = keys.next();
        node.value = (V) "";
        node = successor(node);
      }
  }

  /**
   * Deserializes this object from the given stream.
   *
   * @param s the stream to read from
   * @throws ClassNotFoundException if the underlying stream fails
   * @throws IOException if the underlying stream fails
   * @serialData the <i>size</i> (int), followed by key (Object) and value
   *             (Object) pairs in sorted order
   */
  private void readObject(ObjectInputStream s)
    throws IOException, ClassNotFoundException
  {
    s.defaultReadObject();
    int size = s.readInt();
    putFromObjStream(s, size, true);
  }

  /**
   * Remove node from tree. This will increment modCount and decrement size.
   * Node must exist in the tree. Package visible for use by nested classes.
   *
   * @param node the node to remove
   */
  final void removeNode(Node<K,V> node)
  {
    Node<K,V> splice;
    Node<K,V> child;

    modCount++;
    size--;

    // Find splice, the node at the position to actually remove from the tree.
    if (node.left == nil)
      {
        // Node to be deleted has 0 or 1 children.
        splice = node;
        child = node.right;
      }
    else if (node.right == nil)
      {
        // Node to be deleted has 1 child.
        splice = node;
        child = node.left;
      }
    else
      {
        // Node has 2 children. Splice is node's predecessor, and we swap
        // its contents into node.
        splice = node.left;
        while (splice.right != nil)
          splice = splice.right;
        child = splice.left;
        node.key = splice.key;
        node.value = splice.value;
      }

    // Unlink splice from the tree.
    Node parent = splice.parent;
    if (child != nil)
      child.parent = parent;
    if (parent == nil)
      {
        // Special case for 0 or 1 node remaining.
        root = child;
        return;
      }
    if (splice == parent.left)
      parent.left = child;
    else
      parent.right = child;

    if (splice.color == BLACK)
      deleteFixup(child, parent);
  }

  /**
   * Rotate node n to the left.
   *
   * @param node the node to rotate
   */
  private void rotateLeft(Node<K,V> node)
  {
    Node child = node.right;
    // if (node == nil || child == nil)
    //   throw new InternalError();

    // Establish node.right link.
    node.right = child.left;
    if (child.left != nil)
      child.left.parent = node;

    // Establish child->parent link.
    child.parent = node.parent;
    if (node.parent != nil)
      {
        if (node == node.parent.left)
          node.parent.left = child;
        else
          node.parent.right = child;
      }
    else
      root = child;

    // Link n and child.
    child.left = node;
    node.parent = child;
  }

  /**
   * Rotate node n to the right.
   *
   * @param node the node to rotate
   */
  private void rotateRight(Node<K,V> node)
  {
    Node child = node.left;
    // if (node == nil || child == nil)
    //   throw new InternalError();

    // Establish node.left link.
    node.left = child.right;
    if (child.right != nil)
      child.right.parent = node;

    // Establish child->parent link.
    child.parent = node.parent;
    if (node.parent != nil)
      {
        if (node == node.parent.right)
          node.parent.right = child;
        else
          node.parent.left = child;
      }
    else
      root = child;

    // Link n and child.
    child.right = node;
    node.parent = child;
  }

  /**
   * Return the node following the given one, or nil if there isn't one.
   * Package visible for use by nested classes.
   *
   * @param node the current node, not nil
   * @return the next node in sorted order
   */
  final Node<K,V> successor(Node<K,V> node)
  {
    if (node.right != nil)
      {
        node = node.right;
        while (node.left != nil)
          node = node.left;
        return node;
      }

    Node<K,V> parent = node.parent;
    // Exploit fact that nil.right == nil and node is non-nil.
    while (node == parent.right)
      {
        node = parent;
        parent = parent.parent;
      }
    return parent;
  }

  /**
   * Serializes this object to the given stream.
   *
   * @param s the stream to write to
   * @throws IOException if the underlying stream fails
   * @serialData the <i>size</i> (int), followed by key (Object) and value
   *             (Object) pairs in sorted order
   */
  private void writeObject(ObjectOutputStream s) throws IOException
  {
    s.defaultWriteObject();

    Node node = firstNode();
    s.writeInt(size);
    while (node != nil)
      {
        s.writeObject(node.key);
        s.writeObject(node.value);
        node = successor(node);
      }
  }

  /**
   * Iterate over TreeMap's entries. This implementation is parameterized
   * to give a sequential view of keys, values, or entries.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private final class TreeIterator implements Iterator
  {
    /**
     * The type of this Iterator: {@link #KEYS}, {@link #VALUES},
     * or {@link #ENTRIES}.
     */
    private final int type;
    /** The number of modifications to the backing Map that we know about. */
    private int knownMod = modCount;
    /** The last Entry returned by a next() call. */
    private Node last;
    /** The next entry that should be returned by next(). */
    private Node next;
    /**
     * The last node visible to this iterator. This is used when iterating
     * on a SubMap.
     */
    private final Node max;

    /**
     * Construct a new TreeIterator with the supplied type.
     * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
     */
    TreeIterator(int type)
    {
      this(type, firstNode(), nil);
    }

    /**
     * Construct a new TreeIterator with the supplied type. Iteration will
     * be from "first" (inclusive) to "max" (exclusive).
     *
     * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
     * @param first where to start iteration, nil for empty iterator
     * @param max the cutoff for iteration, nil for all remaining nodes
     */
    TreeIterator(int type, Node first, Node max)
    {
      this.type = type;
      this.next = first;
      this.max = max;
    }

    /**
     * Returns true if the Iterator has more elements.
     * @return true if there are more elements
     */
    public boolean hasNext()
    {
      return next != max;
    }

    /**
     * Returns the next element in the Iterator's sequential view.
     * @return the next element
     * @throws ConcurrentModificationException if the TreeMap was modified
     * @throws NoSuchElementException if there is none
     */
    public Object next()
    {
      if (knownMod != modCount)
        throw new ConcurrentModificationException();
      if (next == max)
        throw new NoSuchElementException();
      last = next;
      next = successor(last);

      if (type == VALUES)
        return last.value;
      else if (type == KEYS)
        return last.key;
      return last;
    }

    /**
     * Removes from the backing TreeMap the last element which was fetched
     * with the <code>next()</code> method.
     * @throws ConcurrentModificationException if the TreeMap was modified
     * @throws IllegalStateException if called when there is no last element
     */
    public void remove()
    {
      if (last == null)
        throw new IllegalStateException();
      if (knownMod != modCount)
        throw new ConcurrentModificationException();

      removeNode(last);
      last = null;
      knownMod++;
    }
  } // class TreeIterator

  /**
   * Implementation of {@link #subMap(Object, Object)} and other map
   * ranges. This class provides a view of a portion of the original backing
   * map, and throws {@link IllegalArgumentException} for attempts to
   * access beyond that range.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private final class SubMap
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>
  {
    /**
     * The lower range of this view, inclusive, or nil for unbounded.
     * Package visible for use by nested classes.
     */
    final K minKey;

    /**
     * The upper range of this view, exclusive, or nil for unbounded.
     * Package visible for use by nested classes.
     */
    final K maxKey;

    /**
     * The cache for {@link #entrySet()}.
     */
    private Set<Map.Entry<K,V>> entries;

    /**
     * The cache for {@link #descendingMap()}.
     */
    private NavigableMap<K,V> descendingMap;

    /**
     * The cache for {@link #navigableKeySet()}.
     */
    private NavigableSet<K> nKeys;

    /**
     * Create a SubMap representing the elements between minKey (inclusive)
     * and maxKey (exclusive). If minKey is nil, SubMap has no lower bound
     * (headMap). If maxKey is nil, the SubMap has no upper bound (tailMap).
     *
     * @param minKey the lower bound
     * @param maxKey the upper bound
     * @throws IllegalArgumentException if minKey &gt; maxKey
     */
    SubMap(K minKey, K maxKey)
    {
      if (minKey != nil && maxKey != nil && compare(minKey, maxKey) > 0)
        throw new IllegalArgumentException("fromKey > toKey");
      this.minKey = minKey;
      this.maxKey = maxKey;
    }

    /**
     * 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. Package visible for use by nested classes.
     *
     * @param key the key to check
     * @return true if the key is in range
     */
    boolean keyInRange(K key)
    {
      return ((minKey == nil || compare(key, minKey) >= 0)
              && (maxKey == nil || compare(key, maxKey) < 0));
    }

    public Entry<K,V> ceilingEntry(K key)
    {
      Entry<K,V> n = TreeMap.this.ceilingEntry(key);
      if (n != null && keyInRange(n.getKey()))
        return n;
      return null;
    }

    public K ceilingKey(K key)
    {
      K found = TreeMap.this.ceilingKey(key);
      if (keyInRange(found))
        return found;
      else
        return null;
    }

    public NavigableSet<K> descendingKeySet()
    {
      return descendingMap().navigableKeySet();
    }

    public NavigableMap<K,V> descendingMap()
    {
      if (descendingMap == null)
        descendingMap = new DescendingMap(this);
      return descendingMap;
    }

    public void clear()
    {
      Node next = lowestGreaterThan(minKey, true);
      Node max = lowestGreaterThan(maxKey, false);
      while (next != max)
        {
          Node current = next;
          next = successor(current);
          removeNode(current);
        }
    }

    public Comparator<? super K> comparator()
    {
      return comparator;
    }

    public boolean containsKey(Object key)
    {
      return keyInRange((K) key) && TreeMap.this.containsKey(key);
    }

    public boolean containsValue(Object value)
    {
      Node node = lowestGreaterThan(minKey, true);
      Node max = lowestGreaterThan(maxKey, false);
      while (node != max)
        {
          if (equals(value, node.getValue()))
            return true;
          node = successor(node);
        }
      return false;
    }

    public Set<Map.Entry<K,V>> entrySet()
    {
      if (entries == null)
        // Create an AbstractSet with custom implementations of those methods
        // that can be overriden easily and efficiently.
        entries = new SubMap.NavigableEntrySet();
      return entries;
    }

    public Entry<K,V> firstEntry()
    {
      Node<K,V> node = lowestGreaterThan(minKey, true);
      if (node == nil || ! keyInRange(node.key))
        return null;
      return node;
    }

    public K firstKey()
    {
      Entry<K,V> e = firstEntry();
      if (e == null)
        throw new NoSuchElementException();
      return e.getKey();
    }

    public Entry<K,V> floorEntry(K key)
    {
      Entry<K,V> n = TreeMap.this.floorEntry(key);
      if (n != null && keyInRange(n.getKey()))
        return n;
      return null;
    }

    public K floorKey(K key)
    {
      K found = TreeMap.this.floorKey(key);
      if (keyInRange(found))
        return found;
      else
        return null;
    }

    public V get(Object key)
    {
      if (keyInRange((K) key))
        return TreeMap.this.get(key);
      return null;
    }

    public SortedMap<K,V> headMap(K toKey)
    {
      return headMap(toKey, false);
    }

    public NavigableMap<K,V> headMap(K toKey, boolean inclusive)
    {
      if (!keyInRange(toKey))
        throw new IllegalArgumentException("Key outside submap range");
      return new SubMap(minKey, (inclusive ?
                                 successor(getNode(toKey)).key : toKey));
    }

    public Set<K> keySet()
    {
      if (this.keys == null)
        // Create an AbstractSet with custom implementations of those methods
        // that can be overriden easily and efficiently.
        this.keys = new SubMap.KeySet();
      return this.keys;
    }

    public Entry<K,V> higherEntry(K key)
    {
      Entry<K,V> n = TreeMap.this.higherEntry(key);
      if (n != null && keyInRange(n.getKey()))
        return n;
      return null;
    }

    public K higherKey(K key)
    {
      K found = TreeMap.this.higherKey(key);
      if (keyInRange(found))
        return found;
      else
        return null;
    }

    public Entry<K,V> lastEntry()
    {
      return lowerEntry(maxKey);
    }

    public K lastKey()
    {
      Entry<K,V> e = lastEntry();
      if (e == null)
        throw new NoSuchElementException();
      return e.getKey();
    }

    public Entry<K,V> lowerEntry(K key)
    {
      Entry<K,V> n = TreeMap.this.lowerEntry(key);
      if (n != null && keyInRange(n.getKey()))
        return n;
      return null;
    }

    public K lowerKey(K key)
    {
      K found = TreeMap.this.lowerKey(key);
      if (keyInRange(found))
        return found;
      else
        return null;
    }

    public NavigableSet<K> navigableKeySet()
    {
      if (this.nKeys == null)
        // Create an AbstractSet with custom implementations of those methods
        // that can be overriden easily and efficiently.
        this.nKeys = new SubMap.NavigableKeySet();
      return this.nKeys;
    }

    public Entry<K,V> pollFirstEntry()
    {
      Entry<K,V> e = firstEntry();
      if (e != null)
        removeNode((Node<K,V>) e);
      return e;
    }

    public Entry<K,V> pollLastEntry()
    {
      Entry<K,V> e = lastEntry();
      if (e != null)
        removeNode((Node<K,V>) e);
      return e;
    }

    public V put(K key, V value)
    {
      if (! keyInRange(key))
        throw new IllegalArgumentException("Key outside range");
      return TreeMap.this.put(key, value);
    }

    public V remove(Object key)
    {
      if (keyInRange((K)key))
        return TreeMap.this.remove(key);
      return null;
    }

    public int size()
    {
      Node node = lowestGreaterThan(minKey, true);
      Node max = lowestGreaterThan(maxKey, false);
      int count = 0;
      while (node != max)
        {
          count++;
          node = successor(node);
        }
      return count;
    }

    public SortedMap<K,V> subMap(K fromKey, K toKey)
    {
      return subMap(fromKey, true, toKey, false);
    }

    public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
                                    K toKey, boolean toInclusive)
    {
      if (! keyInRange(fromKey) || ! keyInRange(toKey))
        throw new IllegalArgumentException("key outside range");
      return new SubMap(fromInclusive ? fromKey : successor(getNode(fromKey)).key,
                        toInclusive ? successor(getNode(toKey)).key : toKey);
    }

    public SortedMap<K, V> tailMap(K fromKey)
    {
      return tailMap(fromKey, true);
    }

    public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive)
    {
      if (! keyInRange(fromKey))
        throw new IllegalArgumentException("key outside range");
      return new SubMap(inclusive ? fromKey : successor(getNode(fromKey)).key,
                        maxKey);
    }

    public Collection<V> values()
    {
      if (this.values == null)
        // Create an AbstractCollection with custom implementations of those
        // methods that can be overriden easily and efficiently.
        this.values = new AbstractCollection()
        {
          public int size()
          {
            return SubMap.this.size();
          }

          public Iterator<V> iterator()
          {
            Node first = lowestGreaterThan(minKey, true);
            Node max = lowestGreaterThan(maxKey, false);
            return new TreeIterator(VALUES, first, max);
          }

          public void clear()
          {
            SubMap.this.clear();
          }
        };
      return this.values;
    }

    private class KeySet
      extends AbstractSet<K>
    {
      public int size()
      {
        return SubMap.this.size();
      }

      public Iterator<K> iterator()
      {
        Node first = lowestGreaterThan(minKey, true);
        Node max = lowestGreaterThan(maxKey, false);
        return new TreeIterator(KEYS, first, max);
      }

      public void clear()
      {
        SubMap.this.clear();
      }

      public boolean contains(Object o)
      {
        if (! keyInRange((K) o))
          return false;
        return getNode((K) o) != nil;
      }

      public boolean remove(Object o)
      {
        if (! keyInRange((K) o))
          return false;
        Node n = getNode((K) o);
        if (n != nil)
          {
            removeNode(n);
            return true;
          }
        return false;
      }

    } // class SubMap.KeySet

    private final class NavigableKeySet
      extends KeySet
      implements NavigableSet<K>
    {

      public K ceiling(K k)
      {
        return SubMap.this.ceilingKey(k);
      }

      public Comparator<? super K> comparator()
      {
        return comparator;
      }

      public Iterator<K> descendingIterator()
      {
        return descendingSet().iterator();
      }

      public NavigableSet<K> descendingSet()
      {
        return new DescendingSet(this);
      }

      public K first()
      {
        return SubMap.this.firstKey();
      }

      public K floor(K k)
      {
        return SubMap.this.floorKey(k);
      }

      public SortedSet<K> headSet(K to)
      {
        return headSet(to, false);
      }

      public NavigableSet<K> headSet(K to, boolean inclusive)
      {
        return SubMap.this.headMap(to, inclusive).navigableKeySet();
      }

      public K higher(K k)
      {
        return SubMap.this.higherKey(k);
      }

      public K last()
      {
        return SubMap.this.lastKey();
      }

      public K lower(K k)
      {
        return SubMap.this.lowerKey(k);
      }

      public K pollFirst()
      {
        return SubMap.this.pollFirstEntry().getKey();
      }

      public K pollLast()
      {
        return SubMap.this.pollLastEntry().getKey();
      }

      public SortedSet<K> subSet(K from, K to)
      {
        return subSet(from, true, to, false);
      }

      public NavigableSet<K> subSet(K from, boolean fromInclusive,
                                    K to, boolean toInclusive)
      {
        return SubMap.this.subMap(from, fromInclusive,
                                  to, toInclusive).navigableKeySet();
      }

      public SortedSet<K> tailSet(K from)
      {
        return tailSet(from, true);
      }

      public NavigableSet<K> tailSet(K from, boolean inclusive)
      {
        return SubMap.this.tailMap(from, inclusive).navigableKeySet();
      }

  } // class SubMap.NavigableKeySet

  /**
   * Implementation of {@link #entrySet()}.
   */
  private class EntrySet
    extends AbstractSet<Entry<K,V>>
  {

    public int size()
    {
      return SubMap.this.size();
    }

    public Iterator<Map.Entry<K,V>> iterator()
    {
      Node first = lowestGreaterThan(minKey, true);
      Node max = lowestGreaterThan(maxKey, false);
      return new TreeIterator(ENTRIES, first, max);
    }

    public void clear()
    {
      SubMap.this.clear();
    }

    public boolean contains(Object o)
    {
      if (! (o instanceof Map.Entry))
        return false;
      Map.Entry<K,V> me = (Map.Entry<K,V>) o;
      K key = me.getKey();
      if (! keyInRange(key))
        return false;
      Node<K,V> n = getNode(key);
      return n != nil && AbstractSet.equals(me.getValue(), n.value);
    }

    public boolean remove(Object o)
    {
      if (! (o instanceof Map.Entry))
        return false;
      Map.Entry<K,V> me = (Map.Entry<K,V>) o;
      K key = me.getKey();
      if (! keyInRange(key))
        return false;
      Node<K,V> n = getNode(key);
      if (n != nil && AbstractSet.equals(me.getValue(), n.value))
        {
          removeNode(n);
          return true;
        }
      return false;
    }
  } // class SubMap.EntrySet

    private final class NavigableEntrySet
      extends EntrySet
      implements NavigableSet<Entry<K,V>>
    {

      public Entry<K,V> ceiling(Entry<K,V> e)
      {
        return SubMap.this.ceilingEntry(e.getKey());
      }

      public Comparator<? super Entry<K,V>> comparator()
      {
        return new Comparator<Entry<K,V>>()
          {
            public int compare(Entry<K,V> t1, Entry<K,V> t2)
              {
                return comparator.compare(t1.getKey(), t2.getKey());
              }
          };
      }

      public Iterator<Entry<K,V>> descendingIterator()
      {
        return descendingSet().iterator();
      }

      public NavigableSet<Entry<K,V>> descendingSet()
      {
        return new DescendingSet(this);
      }

      public Entry<K,V> first()
      {
        return SubMap.this.firstEntry();
      }

      public Entry<K,V> floor(Entry<K,V> e)
      {
        return SubMap.this.floorEntry(e.getKey());
      }

      public SortedSet<Entry<K,V>> headSet(Entry<K,V> to)
      {
        return headSet(to, false);
      }

      public NavigableSet<Entry<K,V>> headSet(Entry<K,V> to, boolean inclusive)
      {
        return (NavigableSet<Entry<K,V>>)
          SubMap.this.headMap(to.getKey(), inclusive).entrySet();
      }

      public Entry<K,V> higher(Entry<K,V> e)
      {
        return SubMap.this.higherEntry(e.getKey());
      }

      public Entry<K,V> last()
      {
        return SubMap.this.lastEntry();
      }

      public Entry<K,V> lower(Entry<K,V> e)
      {
        return SubMap.this.lowerEntry(e.getKey());
      }

      public Entry<K,V> pollFirst()
      {
        return SubMap.this.pollFirstEntry();
      }

      public Entry<K,V> pollLast()
      {
        return SubMap.this.pollLastEntry();
      }

      public SortedSet<Entry<K,V>> subSet(Entry<K,V> from, Entry<K,V> to)
      {
        return subSet(from, true, to, false);
      }

      public NavigableSet<Entry<K,V>> subSet(Entry<K,V> from, boolean fromInclusive,
                                             Entry<K,V> to, boolean toInclusive)
      {
        return (NavigableSet<Entry<K,V>>)
          SubMap.this.subMap(from.getKey(), fromInclusive,
                             to.getKey(), toInclusive).entrySet();
      }

      public SortedSet<Entry<K,V>> tailSet(Entry<K,V> from)
      {
        return tailSet(from, true);
      }

      public NavigableSet<Entry<K,V>> tailSet(Entry<K,V> from, boolean inclusive)
      {
        return (NavigableSet<Entry<K,V>>)
          SubMap.this.tailMap(from.getKey(), inclusive).navigableKeySet();
      }

  } // class SubMap.NavigableEntrySet

} // class SubMap

  /**
   * Returns the entry associated with the least or lowest key
   * that is greater than or equal to the specified key, or
   * <code>null</code> if there is no such key.
   *
   * @param key the key relative to the returned entry.
   * @return the entry with the least key greater than or equal
   *         to the given key, or <code>null</code> if there is
   *         no such key.
   * @throws ClassCastException if the specified key can not
   *                            be compared with those in the map.
   * @throws NullPointerException if the key is <code>null</code>
   *                              and this map either uses natural
   *                              ordering or a comparator that does
   *                              not permit null keys.
   * @since 1.6
   */
  public Entry<K,V> ceilingEntry(K key)
  {
    Node<K,V> n = lowestGreaterThan(key, false);
    return (n == nil) ? null : n;
  }

  /**
   * Returns the the least or lowest key that is greater than
   * or equal to the specified key, or <code>null</code> if
   * there is no such key.
   *
   * @param key the key relative to the returned entry.
   * @return the least key greater than or equal to the given key,
   *         or <code>null</code> if there is no such key.
   * @throws ClassCastException if the specified key can not
   *                            be compared with those in the map.
   * @throws NullPointerException if the key is <code>null</code>
   *                              and this map either uses natural
   *                              ordering or a comparator that does
   *                              not permit null keys.
   * @since 1.6
   */
  public K ceilingKey(K key)
  {
    Entry<K,V> e = ceilingEntry(key);
    return (e == null) ? null : e.getKey();
  }

  /**
   * Returns a reverse ordered {@link NavigableSet} view of this
   * map's keys. The set is backed by the {@link TreeMap}, so changes
   * in one show up in the other.  The set supports element removal,
   * but not element addition.
   *
   * @return a reverse ordered set view of the keys.
   * @since 1.6
   * @see #descendingMap()
   */
  public NavigableSet<K> descendingKeySet()
  {
    return descendingMap().navigableKeySet();
  }

  /**
   * Returns a view of the map in reverse order.  The descending map
   * is backed by the original map, so that changes affect both maps.
   * Any changes occurring to either map while an iteration is taking
   * place (with the exception of a {@link Iterator#remove()} operation)
   * result in undefined behaviour from the iteration.  The ordering
   * of the descending map is the same as for a map with a
   * {@link Comparator} given by {@link Collections#reverseOrder()},
   * and calling {@link #descendingMap()} on the descending map itself
   * results in a view equivalent to the original map.
   *
   * @return a reverse order view of the map.
   * @since 1.6
   */
  public NavigableMap<K,V> descendingMap()
  {
    if (descendingMap == null)
      descendingMap = new DescendingMap<K,V>(this);
    return descendingMap;
  }

  /**
   * Returns the entry associated with the least or lowest key
   * in the map, or <code>null</code> if the map is empty.
   *
   * @return the lowest entry, or <code>null</code> if the map
   *         is empty.
   * @since 1.6
   */
  public Entry<K,V> firstEntry()
  {
    Node<K,V> n = firstNode();
    return (n == nil) ? null : n;
  }

  /**
   * Returns the entry associated with the greatest or highest key
   * that is less than or equal to the specified key, or
   * <code>null</code> if there is no such key.
   *
   * @param key the key relative to the returned entry.
   * @return the entry with the greatest key less than or equal
   *         to the given key, or <code>null</code> if there is
   *         no such key.
   * @throws ClassCastException if the specified key can not
   *                            be compared with those in the map.
   * @throws NullPointerException if the key is <code>null</code>
   *                              and this map either uses natural
   *                              ordering or a comparator that does
   *                              not permit null keys.
   * @since 1.6
   */
  public Entry<K,V> floorEntry(K key)
  {
    Node<K,V> n = highestLessThan(key, true);
    return (n == nil) ? null : n;
  }

  /**
   * Returns the the greatest or highest key that is less than
   * or equal to the specified key, or <code>null</code> if
   * there is no such key.
   *
   * @param key the key relative to the returned entry.
   * @return the greatest key less than or equal to the given key,
   *         or <code>null</code> if there is no such key.
   * @throws ClassCastException if the specified key can not
   *                            be compared with those in the map.
   * @throws NullPointerException if the key is <code>null</code>
   *                              and this map either uses natural
   *                              ordering or a comparator that does
   *                              not permit null keys.
   * @since 1.6
   */
  public K floorKey(K key)
  {
    Entry<K,V> e = floorEntry(key);
    return (e == null) ? null : e.getKey();
  }

  /**
   * Returns the entry associated with the least or lowest key
   * that is strictly greater than the specified key, or
   * <code>null</code> if there is no such key.
   *
   * @param key the key relative to the returned entry.
   * @return the entry with the least key greater than
   *         the given key, or <code>null</code> if there is
   *         no such key.
   * @throws ClassCastException if the specified key can not
   *                            be compared with those in the map.
   * @throws NullPointerException if the key is <code>null</code>
   *                              and this map either uses natural
   *                              ordering or a comparator that does
   *                              not permit null keys.
   * @since 1.6
   */
  public Entry<K,V> higherEntry(K key)
  {
    Node<K,V> n = lowestGreaterThan(key, false, false);
    return (n == nil) ? null : n;
  }

  /**
   * Returns the the least or lowest key that is strictly
   * greater than the specified key, or <code>null</code> if
   * there is no such key.
   *
   * @param key the key relative to the returned entry.
   * @return the least key greater than the given key,
   *         or <code>null</code> if there is no such key.
   * @throws ClassCastException if the specified key can not
   *                            be compared with those in the map.
   * @throws NullPointerException if the key is <code>null</code>
   *                              and this map either uses natural
   *                              ordering or a comparator that does
   *                              not permit null keys.
   * @since 1.6
   */
  public K higherKey(K key)
  {
    Entry<K,V> e = higherEntry(key);
    return (e == null) ? null : e.getKey();
  }

  /**
   * Returns the entry associated with the greatest or highest key
   * in the map, or <code>null</code> if the map is empty.
   *
   * @return the highest entry, or <code>null</code> if the map
   *         is empty.
   * @since 1.6
   */
  public Entry<K,V> lastEntry()
  {
    Node<K,V> n = lastNode();
    return (n == nil) ? null : n;
  }

  /**
   * Returns the entry associated with the greatest or highest key
   * that is strictly less than the specified key, or
   * <code>null</code> if there is no such key.
   *
   * @param key the key relative to the returned entry.
   * @return the entry with the greatest key less than
   *         the given key, or <code>null</code> if there is
   *         no such key.
   * @throws ClassCastException if the specified key can not
   *                            be compared with those in the map.
   * @throws NullPointerException if the key is <code>null</code>
   *                              and this map either uses natural
   *                              ordering or a comparator that does
   *                              not permit null keys.
   * @since 1.6
   */
  public Entry<K,V> lowerEntry(K key)
  {
    Node<K,V> n = highestLessThan(key);
    return (n == nil) ? null : n;
  }

  /**
   * Returns the the greatest or highest key that is strictly
   * less than the specified key, or <code>null</code> if
   * there is no such key.
   *
   * @param key the key relative to the returned entry.
   * @return the greatest key less than the given key,
   *         or <code>null</code> if there is no such key.
   * @throws ClassCastException if the specified key can not
   *                            be compared with those in the map.
   * @throws NullPointerException if the key is <code>null</code>
   *                              and this map either uses natural
   *                              ordering or a comparator that does
   *                              not permit null keys.
   * @since 1.6
   */
  public K lowerKey(K key)
  {
    Entry<K,V> e = lowerEntry(key);
    return (e == null) ? null : e.getKey();
  }

  /**
   * Returns a {@link NavigableSet} view of this map's keys. The set is
   * backed by the {@link TreeMap}, so changes in one show up in the other.
   * Any changes occurring to either while an iteration is taking
   * place (with the exception of a {@link Iterator#remove()} operation)
   * result in undefined behaviour from the iteration.  The ordering
   * The set supports element removal, but not element addition.
   *
   * @return a {@link NavigableSet} view of the keys.
   * @since 1.6
   */
  public NavigableSet<K> navigableKeySet()
  {
    if (nKeys == null)
      nKeys = new NavigableKeySet();
    return nKeys;
  }

  /**
   * Removes and returns the entry associated with the least
   * or lowest key in the map, or <code>null</code> if the map
   * is empty.
   *
   * @return the removed first entry, or <code>null</code> if the
   *         map is empty.
   * @since 1.6
   */
  public Entry<K,V> pollFirstEntry()
  {
    Entry<K,V> e = firstEntry();
    if (e != null)
      removeNode((Node<K,V>)e);
    return e;
  }

  /**
   * Removes and returns the entry associated with the greatest
   * or highest key in the map, or <code>null</code> if the map
   * is empty.
   *
   * @return the removed last entry, or <code>null</code> if the
   *         map is empty.
   * @since 1.6
   */
  public Entry<K,V> pollLastEntry()
  {
    Entry<K,V> e = lastEntry();
    if (e != null)
      removeNode((Node<K,V>)e);
    return e;
  }

  /**
   * Implementation of {@link #descendingMap()} and associated
   * derivatives. This class provides a view of the
   * original backing map in reverse order, and throws
   * {@link IllegalArgumentException} for attempts to
   * access beyond that range.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   */
  private static final class DescendingMap<DK,DV>
    implements NavigableMap<DK,DV>
  {

    /**
     * The cache for {@link #entrySet()}.
     */
    private Set<Map.Entry<DK,DV>> entries;

    /**
     * The cache for {@link #keySet()}.
     */
    private Set<DK> keys;

    /**
     * The cache for {@link #navigableKeySet()}.
     */
    private NavigableSet<DK> nKeys;

    /**
     * The cache for {@link #values()}.
     */
    private Collection<DV> values;

    /**
     * The backing {@link NavigableMap}.
     */
    private NavigableMap<DK,DV> map;

    /**
     * Create a {@link DescendingMap} around the specified
     * map.
     *
     * @param map the map to wrap.
     */
    public DescendingMap(NavigableMap<DK,DV> map)
    {
      this.map = map;
    }

    public Map.Entry<DK,DV> ceilingEntry(DK key)
    {
      return map.floorEntry(key);
    }

    public DK ceilingKey(DK key)
    {
      return map.floorKey(key);
    }

    public void clear()
    {
      map.clear();
    }

    public Comparator<? super DK> comparator()
    {
      return Collections.reverseOrder(map.comparator());
    }

    public boolean containsKey(Object o)
    {
      return map.containsKey(o);
    }

    public boolean containsValue(Object o)
    {
      return map.containsValue(o);
    }

    public NavigableSet<DK> descendingKeySet()
    {
      return descendingMap().navigableKeySet();
    }

    public NavigableMap<DK,DV> descendingMap()
    {
      return map;
    }

    public Set<Entry<DK,DV>> entrySet()
    {
      if (entries == null)
        entries =
          new DescendingSet<Entry<DK,DV>>((NavigableSet<Entry<DK,DV>>)
                                          map.entrySet());
      return entries;
    }

    public boolean equals(Object o)
    {
      return map.equals(o);
    }

    public Entry<DK,DV> firstEntry()
    {
      return map.lastEntry();
    }

    public DK firstKey()
    {
      return map.lastKey();
    }

    public Entry<DK,DV> floorEntry(DK key)
    {
      return map.ceilingEntry(key);
    }

    public DK floorKey(DK key)
    {
      return map.ceilingKey(key);
    }

    public DV get(Object key)
    {
      return map.get(key);
    }

    public int hashCode()
    {
      return map.hashCode();
    }

    public SortedMap<DK,DV> headMap(DK toKey)
    {
      return headMap(toKey, false);
    }

    public NavigableMap<DK,DV> headMap(DK toKey, boolean inclusive)
    {
      return new DescendingMap(map.tailMap(toKey, inclusive));
    }

    public Entry<DK,DV> higherEntry(DK key)
    {
      return map.lowerEntry(key);
    }

    public DK higherKey(DK key)
    {
      return map.lowerKey(key);
    }

    public Set<DK> keySet()
    {
      if (keys == null)
        keys = new DescendingSet<DK>(map.navigableKeySet());
      return keys;
    }

    public boolean isEmpty()
    {
      return map.isEmpty();
    }

    public Entry<DK,DV> lastEntry()
    {
      return map.firstEntry();
    }

    public DK lastKey()
    {
      return map.firstKey();
    }

    public Entry<DK,DV> lowerEntry(DK key)
    {
      return map.higherEntry(key);
    }

    public DK lowerKey(DK key)
    {
      return map.higherKey(key);
    }

    public NavigableSet<DK> navigableKeySet()
    {
      if (nKeys == null)
        nKeys = new DescendingSet<DK>(map.navigableKeySet());
      return nKeys;
    }

    public Entry<DK,DV> pollFirstEntry()
    {
      return pollLastEntry();
    }

    public Entry<DK,DV> pollLastEntry()
    {
      return pollFirstEntry();
    }

    public DV put(DK key, DV value)
    {
      return map.put(key, value);
    }

    public void putAll(Map<? extends DK, ? extends DV> m)
    {
      map.putAll(m);
    }

    public DV remove(Object key)
    {
      return map.remove(key);
    }

    public int size()
    {
      return map.size();
    }

    public SortedMap<DK,DV> subMap(DK fromKey, DK toKey)
    {
      return subMap(fromKey, true, toKey, false);
    }

    public NavigableMap<DK,DV> subMap(DK fromKey, boolean fromInclusive,
                                      DK toKey, boolean toInclusive)
    {
      return new DescendingMap(map.subMap(fromKey, fromInclusive,
                                          toKey, toInclusive));
    }

    public SortedMap<DK,DV> tailMap(DK fromKey)
    {
      return tailMap(fromKey, true);
    }

    public NavigableMap<DK,DV> tailMap(DK fromKey, boolean inclusive)
    {
      return new DescendingMap(map.headMap(fromKey, inclusive));
    }

    public String toString()
    {
      CPStringBuilder r = new CPStringBuilder("{");
      final Iterator<Entry<DK,DV>> it = entrySet().iterator();
      while (it.hasNext())
      {
        final Entry<DK,DV> e = it.next();
        r.append(e.getKey());
        r.append('=');
        r.append(e.getValue());
        r.append(", ");
      }
      r.replace(r.length() - 2, r.length(), "}");
      return r.toString();
    }

    public Collection<DV> values()
    {
      if (values == null)
        // Create an AbstractCollection with custom implementations of those
        // methods that can be overriden easily and efficiently.
        values = new AbstractCollection()
          {
            public int size()
            {
              return DescendingMap.this.size();
            }

            public Iterator<DV> iterator()
            {
              return new Iterator<DV>()
                {
                  /** The last Entry returned by a next() call. */
                  private Entry<DK,DV> last;

                  /** The next entry that should be returned by next(). */
                  private Entry<DK,DV> next = firstEntry();

                  public boolean hasNext()
                  {
                    return next != null;
                  }

                  public DV next()
                  {
                    if (next == null)
                      throw new NoSuchElementException();
                    last = next;
                    next = higherEntry(last.getKey());

                    return last.getValue();
                  }

                  public void remove()
                  {
                    if (last == null)
                      throw new IllegalStateException();

                    DescendingMap.this.remove(last.getKey());
                    last = null;
                  }
                };
            }

            public void clear()
            {
              DescendingMap.this.clear();
            }
          };
      return values;
    }

  } // class DescendingMap

  /**
   * Implementation of {@link #keySet()}.
   */
  private class KeySet
    extends AbstractSet<K>
  {

    public int size()
    {
      return size;
    }

    public Iterator<K> iterator()
    {
      return new TreeIterator(KEYS);
    }

    public void clear()
    {
      TreeMap.this.clear();
    }

    public boolean contains(Object o)
    {
      return containsKey(o);
    }

    public boolean remove(Object key)
    {
      Node<K,V> n = getNode((K) key);
      if (n == nil)
        return false;
      removeNode(n);
      return true;
    }
  } // class KeySet

  /**
   * Implementation of {@link #navigableKeySet()}.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   */
  private final class NavigableKeySet
    extends KeySet
    implements NavigableSet<K>
  {

    public K ceiling(K k)
    {
      return ceilingKey(k);
    }

    public Comparator<? super K> comparator()
    {
      return comparator;
    }

    public Iterator<K> descendingIterator()
    {
      return descendingSet().iterator();
    }

    public NavigableSet<K> descendingSet()
    {
      return new DescendingSet<K>(this);
    }

    public K first()
    {
      return firstKey();
    }

    public K floor(K k)
    {
      return floorKey(k);
    }

    public SortedSet<K> headSet(K to)
    {
      return headSet(to, false);
    }

    public NavigableSet<K> headSet(K to, boolean inclusive)
    {
      return headMap(to, inclusive).navigableKeySet();
    }

    public K higher(K k)
    {
      return higherKey(k);
    }

    public K last()
    {
      return lastKey();
    }

    public K lower(K k)
    {
      return lowerKey(k);
    }

    public K pollFirst()
    {
      return pollFirstEntry().getKey();
    }

    public K pollLast()
    {
      return pollLastEntry().getKey();
    }

    public SortedSet<K> subSet(K from, K to)
    {
      return subSet(from, true, to, false);
    }

    public NavigableSet<K> subSet(K from, boolean fromInclusive,
                                  K to, boolean toInclusive)
    {
      return subMap(from, fromInclusive,
                    to, toInclusive).navigableKeySet();
    }

    public SortedSet<K> tailSet(K from)
    {
      return tailSet(from, true);
    }

    public NavigableSet<K> tailSet(K from, boolean inclusive)
    {
      return tailMap(from, inclusive).navigableKeySet();
    }


  } // class NavigableKeySet

  /**
   * Implementation of {@link #descendingSet()} and associated
   * derivatives. This class provides a view of the
   * original backing set in reverse order, and throws
   * {@link IllegalArgumentException} for attempts to
   * access beyond that range.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   */
  private static final class DescendingSet<D>
    implements NavigableSet<D>
  {

    /**
     * The backing {@link NavigableSet}.
     */
    private NavigableSet<D> set;

    /**
     * Create a {@link DescendingSet} around the specified
     * set.
     *
     * @param map the set to wrap.
     */
    public DescendingSet(NavigableSet<D> set)
    {
      this.set = set;
    }

    public boolean add(D e)
    {
      return set.add(e);
    }

    public boolean addAll(Collection<? extends D> c)
    {
      return set.addAll(c);
    }

    public D ceiling(D e)
    {
      return set.floor(e);
    }

    public void clear()
    {
      set.clear();
    }

    public Comparator<? super D> comparator()
    {
      return Collections.reverseOrder(set.comparator());
    }

    public boolean contains(Object o)
    {
      return set.contains(o);
    }

    public boolean containsAll(Collection<?> c)
    {
      return set.containsAll(c);
    }

    public Iterator<D> descendingIterator()
    {
      return descendingSet().iterator();
    }

    public NavigableSet<D> descendingSet()
    {
      return set;
    }

    public boolean equals(Object o)
    {
      return set.equals(o);
    }

    public D first()
    {
      return set.last();
    }

    public D floor(D e)
    {
      return set.ceiling(e);
    }

    public int hashCode()
    {
      return set.hashCode();
    }

    public SortedSet<D> headSet(D to)
    {
      return headSet(to, false);
    }

    public NavigableSet<D> headSet(D to, boolean inclusive)
    {
      return new DescendingSet(set.tailSet(to, inclusive));
    }

    public D higher(D e)
    {
      return set.lower(e);
    }

    public boolean isEmpty()
    {
      return set.isEmpty();
    }

    public Iterator<D> iterator()
    {
      return new Iterator<D>()
        {

          /** The last element returned by a next() call. */
          private D last;

          /** The next element that should be returned by next(). */
          private D next = first();

          public boolean hasNext()
          {
            return next != null;
          }

          public D next()
          {
            if (next == null)
              throw new NoSuchElementException();
            last = next;
            next = higher(last);

            return last;
          }

          public void remove()
          {
            if (last == null)
              throw new IllegalStateException();

            DescendingSet.this.remove(last);
            last = null;
          }
        };
    }

    public D last()
    {
      return set.first();
    }

    public D lower(D e)
    {
      return set.higher(e);
    }

    public D pollFirst()
    {
      return set.pollLast();
    }

    public D pollLast()
    {
      return set.pollFirst();
    }

    public boolean remove(Object o)
    {
      return set.remove(o);
    }

    public boolean removeAll(Collection<?> c)
    {
      return set.removeAll(c);
    }

    public boolean retainAll(Collection<?> c)
    {
      return set.retainAll(c);
    }

    public int size()
    {
      return set.size();
    }

    public SortedSet<D> subSet(D from, D to)
    {
      return subSet(from, true, to, false);
    }

    public NavigableSet<D> subSet(D from, boolean fromInclusive,
                                  D to, boolean toInclusive)
    {
      return new DescendingSet(set.subSet(from, fromInclusive,
                                          to, toInclusive));
    }

    public SortedSet<D> tailSet(D from)
    {
      return tailSet(from, true);
    }

    public NavigableSet<D> tailSet(D from, boolean inclusive)
    {
      return new DescendingSet(set.headSet(from, inclusive));
    }

    public Object[] toArray()
    {
      D[] array = (D[]) set.toArray();
      Arrays.sort(array, comparator());
      return array;
    }

    public <T> T[] toArray(T[] a)
    {
      T[] array = set.toArray(a);
      Arrays.sort(array, (Comparator<? super T>) comparator());
      return array;
    }

    public String toString()
    {
      CPStringBuilder r = new CPStringBuilder("[");
      final Iterator<D> it = iterator();
      while (it.hasNext())
      {
        final D o = it.next();
        if (o == this)
          r.append("<this>");
        else
          r.append(o);
        r.append(", ");
      }
      r.replace(r.length() - 2, r.length(), "]");
      return r.toString();
    }

  } // class DescendingSet

  private class EntrySet
    extends AbstractSet<Entry<K,V>>
  {
    public int size()
    {
      return size;
    }

    public Iterator<Map.Entry<K,V>> iterator()
    {
      return new TreeIterator(ENTRIES);
    }

    public void clear()
    {
      TreeMap.this.clear();
    }

    public boolean contains(Object o)
    {
      if (! (o instanceof Map.Entry))
        return false;
      Map.Entry<K,V> me = (Map.Entry<K,V>) o;
      Node<K,V> n = getNode(me.getKey());
      return n != nil && AbstractSet.equals(me.getValue(), n.value);
    }

    public boolean remove(Object o)
    {
      if (! (o instanceof Map.Entry))
        return false;
      Map.Entry<K,V> me = (Map.Entry<K,V>) o;
      Node<K,V> n = getNode(me.getKey());
      if (n != nil && AbstractSet.equals(me.getValue(), n.value))
        {
          removeNode(n);
          return true;
        }
      return false;
    }
  }

  private final class NavigableEntrySet
    extends EntrySet
    implements NavigableSet<Entry<K,V>>
  {

    public Entry<K,V> ceiling(Entry<K,V> e)
    {
      return ceilingEntry(e.getKey());
    }

    public Comparator<? super Entry<K,V>> comparator()
    {
      return new Comparator<Entry<K,V>>()
        {
          public int compare(Entry<K,V> t1, Entry<K,V> t2)
          {
            return comparator.compare(t1.getKey(), t2.getKey());
          }
        };
    }

    public Iterator<Entry<K,V>> descendingIterator()
    {
      return descendingSet().iterator();
    }

    public NavigableSet<Entry<K,V>> descendingSet()
    {
      return new DescendingSet(this);
    }

    public Entry<K,V> first()
    {
      return firstEntry();
    }

    public Entry<K,V> floor(Entry<K,V> e)
    {
      return floorEntry(e.getKey());
    }

    public SortedSet<Entry<K,V>> headSet(Entry<K,V> to)
    {
      return headSet(to, false);
    }

    public NavigableSet<Entry<K,V>> headSet(Entry<K,V> to, boolean inclusive)
    {
      return (NavigableSet<Entry<K,V>>) headMap(to.getKey(), inclusive).entrySet();
    }

    public Entry<K,V> higher(Entry<K,V> e)
    {
      return higherEntry(e.getKey());
    }

    public Entry<K,V> last()
    {
      return lastEntry();
    }

    public Entry<K,V> lower(Entry<K,V> e)
    {
      return lowerEntry(e.getKey());
    }

    public Entry<K,V> pollFirst()
    {
      return pollFirstEntry();
    }

    public Entry<K,V> pollLast()
    {
      return pollLastEntry();
    }

    public SortedSet<Entry<K,V>> subSet(Entry<K,V> from, Entry<K,V> to)
    {
      return subSet(from, true, to, false);
    }

    public NavigableSet<Entry<K,V>> subSet(Entry<K,V> from, boolean fromInclusive,
                                           Entry<K,V> to, boolean toInclusive)
    {
      return (NavigableSet<Entry<K,V>>) subMap(from.getKey(), fromInclusive,
                                               to.getKey(), toInclusive).entrySet();
    }

    public SortedSet<Entry<K,V>> tailSet(Entry<K,V> from)
    {
      return tailSet(from, true);
    }

    public NavigableSet<Entry<K,V>> tailSet(Entry<K,V> from, boolean inclusive)
    {
      return (NavigableSet<Entry<K,V>>) tailMap(from.getKey(), inclusive).navigableKeySet();
    }

  } // class NavigableEntrySet

} // class TreeMap
