This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: FYI: libgcj / classpath comparison


I'm checking this in.
It is another libgcj/Classpath comparison.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* libgcj-classpath-compare.html: Rebuilt.

Index: libgcj-classpath-compare.html
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/java/libgcj-classpath-compare.html,v
retrieving revision 1.22
diff -u -r1.22 libgcj-classpath-compare.html
--- libgcj-classpath-compare.html 2001/12/07 23:22:19 1.22
+++ libgcj-classpath-compare.html 2001/12/16 00:13:59
@@ -9,7 +9,7 @@
 cvs Classpath.  It was generated using the <a
 href="scripts/gen-classpath-compare"><code>gen-classpath-compare</code></a>
 script on
-2001-12-07.
+2001-12-15.
 This table intentionally omits certain classes which are not of
 interest.  If the third column shows a "Diff" link, then that means
 the script believes that the class has been merged, but a difference
@@ -36,7 +36,6 @@
 <tr> <td>java.lang.Character</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#eeeeaa">No</td> </tr>
 <tr> <td>java.lang.Class</td> <td>Yes</td> <td bgcolor="#eeeeaa">No</td> <td bgcolor="#eeeeaa">No</td> </tr>
 <tr> <td>java.lang.ClassLoader</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#eeeeaa">No</td> </tr>
-<tr> <td>java.lang.Double</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.lang.Double.diff">Diff</a></td> </tr>
 <tr> <td>java.lang.EcosProcess</td> <td>Yes</td> <td bgcolor="#eeeeaa">No</td> <td bgcolor="#eeeeaa">No</td> </tr>
 <tr> <td>java.lang.Math</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#eeeeaa">No</td> </tr>
 <tr> <td>java.lang.Object</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#eeeeaa">No</td> </tr>
@@ -80,31 +79,18 @@
 <tr> <td>java.text.CollationKey</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#eeeeaa">No</td> </tr>
 <tr> <td>java.text.Collator</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.text.Collator.diff">Diff</a></td> </tr>
 <tr> <td>java.text.RuleBasedCollator</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#eeeeaa">No</td> </tr>
-<tr> <td>java.util.AbstractCollection</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.AbstractCollection.diff">Diff</a></td> </tr>
-<tr> <td>java.util.AbstractList</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.AbstractList.diff">Diff</a></td> </tr>
 <tr> <td>java.util.AbstractMap</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.AbstractMap.diff">Diff</a></td> </tr>
 <tr> <td>java.util.AbstractSequentialList</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.AbstractSequentialList.diff">Diff</a></td> </tr>
 <tr> <td>java.util.AbstractSet</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.AbstractSet.diff">Diff</a></td> </tr>
 <tr> <td>java.util.ArrayList</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.ArrayList.diff">Diff</a></td> </tr>
 <tr> <td>java.util.Arrays</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.Arrays.diff">Diff</a></td> </tr>
-<tr> <td>java.util.BasicMapEntry</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.BasicMapEntry.diff">Diff</a></td> </tr>
-<tr> <td>java.util.BitSet</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.BitSet.diff">Diff</a></td> </tr>
 <tr> <td>java.util.Collections</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.Collections.diff">Diff</a></td> </tr>
-<tr> <td>java.util.Dictionary</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.Dictionary.diff">Diff</a></td> </tr>
-<tr> <td>java.util.HashMap</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.HashMap.diff">Diff</a></td> </tr>
-<tr> <td>java.util.HashSet</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.HashSet.diff">Diff</a></td> </tr>
-<tr> <td>java.util.Hashtable</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.Hashtable.diff">Diff</a></td> </tr>
-<tr> <td>java.util.IdentityHashMap</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.IdentityHashMap.diff">Diff</a></td> </tr>
-<tr> <td>java.util.LinkedHashMap</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.LinkedHashMap.diff">Diff</a></td> </tr>
-<tr> <td>java.util.LinkedHashSet</td> <td bgcolor="#eeeeaa">No</td> <td>Yes</td> <td bgcolor="#eeeeaa">No</td> </tr>
-<tr> <td>java.util.LinkedList</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.LinkedList.diff">Diff</a></td> </tr>
+<tr> <td>java.util.LinkedHashSet</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.LinkedHashSet.diff">Diff</a></td> </tr>
 <tr> <td>java.util.List</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.List.diff">Diff</a></td> </tr>
-<tr> <td>java.util.Stack</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.Stack.diff">Diff</a></td> </tr>
 <tr> <td>java.util.TimeZone</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.TimeZone.diff">Diff</a></td> </tr>
 <tr> <td>java.util.TreeMap</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.TreeMap.diff">Diff</a></td> </tr>
 <tr> <td>java.util.TreeSet</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.TreeSet.diff">Diff</a></td> </tr>
 <tr> <td>java.util.Vector</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.Vector.diff">Diff</a></td> </tr>
-<tr> <td>java.util.WeakHashMap</td> <td>Yes</td> <td>Yes</td> <td bgcolor="#aaaaee"><a href="compare/java.util.WeakHashMap.diff">Diff</a></td> </tr>
 <tr> <td>java.util.prefs.AbstractPreferences</td> <td bgcolor="#eeeeaa">No</td> <td>Yes</td> <td bgcolor="#eeeeaa">No</td> </tr>
 <tr> <td>java.util.prefs.BackingStoreException</td> <td bgcolor="#eeeeaa">No</td> <td>Yes</td> <td bgcolor="#eeeeaa">No</td> </tr>
 <tr> <td>java.util.prefs.InvalidPreferencesFormatException</td> <td bgcolor="#eeeeaa">No</td> <td>Yes</td> <td bgcolor="#eeeeaa">No</td> </tr>
Index: compare/java.io.ObjectInputStream.diff
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/java/compare/java.io.ObjectInputStream.diff,v
retrieving revision 1.2
diff -u -r1.2 java.io.ObjectInputStream.diff
--- compare/java.io.ObjectInputStream.diff 2001/09/26 17:37:43 1.2
+++ compare/java.io.ObjectInputStream.diff 2001/12/16 00:14:00
@@ -1,5 +1,5 @@
---- /home/tromey/gnu/egcs/classpath/classpath/java/io/ObjectInputStream.java	Wed Sep 26 08:18:40 2001
-+++ java/io/ObjectInputStream.java	Thu Apr 26 19:17:10 2001
+--- /home/tromey/gnu/egcs/classpath/classpath/java/io/ObjectInputStream.java	Sat Dec  8 19:19:53 2001
++++ java/io/ObjectInputStream.java	Sat Dec  8 12:12:49 2001
 @@ -27,6 +27,8 @@
  
  package java.io;
@@ -120,6 +120,15 @@
  
       @see ObjectInputStream ()
    */
+@@ -1288,7 +1295,7 @@
+ 
+ 
+   // returns a new instance of REAL_CLASS that has been constructed
+-  // only to th level of CONSTRUCTOR_CLASS (a super class of REAL_CLASS)
++  // only to the level of CONSTRUCTOR_CLASS (a super class of REAL_CLASS)
+   private Object newObject (Class real_class, Class constructor_class)
+   {
+     try
 @@ -1326,34 +1333,182 @@
  
    // this native method is used to get access to the protected method
Index: compare/java.util.AbstractMap.diff
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/java/compare/java.util.AbstractMap.diff,v
retrieving revision 1.1
diff -u -r1.1 java.util.AbstractMap.diff
--- compare/java.util.AbstractMap.diff 2001/11/07 01:23:48 1.1
+++ compare/java.util.AbstractMap.diff 2001/12/16 00:14:00
@@ -1,665 +1,10 @@
 --- /home/tromey/gnu/egcs/classpath/classpath/java/util/AbstractMap.java	Fri Oct 26 16:06:56 2001
-+++ java/util/AbstractMap.java	Tue Oct 16 09:14:34 2001
-@@ -1,5 +1,5 @@
- /* AbstractMap.java -- Abstract implementation of most of Map
--   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
-+   Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
- 
- This file is part of GNU Classpath.
- 
-@@ -25,70 +25,22 @@
- executable file might be covered by the GNU General Public License. */
- 
- 
-+// TO DO:
-+// comments
-+// test suite
-+
- package java.util;
- 
--/**
-- * An abstract implementation of Map to make it easier to create your own
-- * implementations. In order to create an unmodifiable Map, subclass
-- * AbstractMap and implement the <code>entrySet</code> (usually via an
-- * AbstractSet).  To make it modifiable, also implement <code>put</code>,
-- * and have <code>entrySet().iterator()</code> support <code>remove</code>.
-- * <p>
-- *
-- * It is recommended that classes which extend this support at least the
-- * no-argument constructor, and a constructor which accepts another Map.
-- * Further methods in this class may be overridden if you have a more
-- * efficient implementation.
-- *
-- * @author Original author unknown
-- * @author Eric Blake <ebb9@email.byu.edu>
-- * @see Map
-- * @see Collection
-- * @see HashMap
-- * @see LinkedHashMap
-- * @see TreeMap
-- * @see WeakHashMap
-- * @see IdentityHashMap
-- * @since 1.2
-- * @status updated to 1.4
-- */
- public abstract class AbstractMap implements Map
- {
--  /** An "enum" of iterator types. */
--  // Package visible for use by subclasses.
--  static final int KEYS = 0,
--                   VALUES = 1,
--                   ENTRIES = 2;
--
--  /**
--   * The cache for {@link #keySet()}.
--   */
--  // Package visible for use by subclasses.
--  Set keys;
--
--  /**
--   * The cache for {@link #values()}.
--   */
--  // Package visible for use by subclasses.
--  Collection values;
--
-   /**
--   * The main constructor, for use by subclasses.
--   */
--  protected AbstractMap()
--  {
--  }
--
--  /**
--   * Remove all entries from this Map (optional operation). This default
--   * implementation calls entrySet().clear(). NOTE: If the entry set does
--   * not permit clearing, then this will fail, too. Subclasses often
--   * override this for efficiency.  Your implementation of entrySet() should
--   * not call <code>AbstractMap.clear</code> unless you want an infinite loop.
-+   * Remove all entries from this Map. This default implementation calls
-+   * entrySet().clear().
-    *
--   * @throws UnsupportedOperationException if <code>entrySet().clear()</code>
--   *         does not support clearing.
--   * @see Set#clear()
-+   * @throws UnsupportedOperationException
-+   * @specnote The JCL book claims that this implementation always throws 
-+   *           UnsupportedOperationException, while the online docs claim it
-+   *           calls entrySet().clear(). We take the later to be correct.
-    */
-   public void clear()
-   {
-@@ -96,414 +48,246 @@
-   }
- 
-   /**
--   * Create a shallow copy of this Map, no keys or values are copied. The
--   * default implementation simply calls <code>super.clone()</code>.
--   *
--   * @return the shallow clone
--   * @throws CloneNotSupportedException if a subclass is not Cloneable
--   * @see Cloneable
--   * @see Object#clone()
-+   * Create a shallow copy of this Map, no keys or values are copied.
-    */
--  protected Object clone() throws CloneNotSupportedException
-+  protected Object clone () throws CloneNotSupportedException
-   {
--    AbstractMap copy = (AbstractMap) super.clone();
--    // Clear out the caches; they are stale.
--    copy.keys = null;
--    copy.values = null;
--    return copy;
-+    return super.clone ();
-   }
- 
--  /**
--   * Returns true if this contains a mapping for the given key. This
--   * implementation does a linear search, O(n), over the
--   * <code>entrySet()</code>, returning <code>true</code> if a match
--   * is found, <code>false</code> if the iteration ends. Many subclasses
--   * can implement this more efficiently.
--   *
--   * @param key the key to search for
--   * @return true if the map contains the key
--   * @throws NullPointerException if key is <code>null</code> but the map
--   *         does not permit null keys
--   * @see #containsValue(Object)
--   */
-   public boolean containsKey(Object key)
-   {
--    Iterator entries = entrySet().iterator();
--    int pos = size();
--    while (--pos >= 0)
--      if (equals(key, ((Map.Entry) entries.next()).getKey()))
--        return true;
-+    Object k;
-+    Set es = entrySet();
-+    Iterator entries = es.iterator();
-+    int size = size();
-+    for (int pos = 0; pos < size; pos++)
-+      {
-+	k = ((Map.Entry) entries.next()).getKey();
-+	if (key == null ? k == null : key.equals(k))
-+	  return true;
-+      }
-     return false;
-   }
- 
--  /**
--   * Returns true if this contains at least one mapping with the given value.
--   * This implementation does a linear search, O(n), over the
--   * <code>entrySet()</code>, returning <code>true</code> if a match
--   * is found, <code>false</code> if the iteration ends. A match is
--   * defined as <code>(value == null ? v == null : value.equals(v))</code>
--   * Subclasses are unlikely to implement this more efficiently.
--   *
--   * @param value the value to search for
--   * @return true if the map contains the value
--   * @see #containsKey(Object)
--   */
-   public boolean containsValue(Object value)
-   {
--    Iterator entries = entrySet().iterator();
--    int pos = size();
--    while (--pos >= 0)
--      if (equals(value, ((Map.Entry) entries.next()).getValue()))
--        return true;
-+    Object v;
-+    Set es = entrySet();
-+    Iterator entries = es.iterator();
-+    int size = size();
-+    for (int pos = 0; pos < size; pos++)
-+      {
-+	v = ((Map.Entry) entries.next()).getValue();
-+	if (value == null ? v == null : value.equals(v))
-+	  return true;
-+      }
-     return false;
-   }
- 
--  /**
--   * Returns a set view of the mappings in this Map.  Each element in the
--   * set must be an implementation of Map.Entry.  The set is backed by
--   * the map, so that changes in one show up in the other.  Modifications
--   * made while an iterator is in progress cause undefined behavior.  If
--   * the set supports removal, these methods must be valid:
--   * <code>Iterator.remove</code>, <code>Set.remove</code>,
--   * <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
--   * Element addition is not supported via this set.
--   *
--   * @return the entry set
--   * @see Map.Entry
--   */
-   public abstract Set entrySet();
- 
--  /**
--   * Compares the specified object with this map for equality. Returns
--   * <code>true</code> if the other object is a Map with the same mappings,
--   * that is,<br>
--   * <code>o instanceof Map && entrySet().equals(((Map) o).entrySet();</code>
--   *
--   * @param o the object to be compared
--   * @return true if the object equals this map
--   * @see Set#equals(Object)
--   */
-   public boolean equals(Object o)
-   {
--    return (o == this ||
--            (o instanceof Map &&
--             entrySet().equals(((Map) o).entrySet())));
-+    if (o == this)
-+      return true;
-+    if (!(o instanceof Map))
-+      return false;
-+
-+    Map m = (Map) o;
-+    Set s = m.entrySet();
-+    Iterator itr = entrySet().iterator();
-+    int size = size();
-+
-+    if (m.size() != size)
-+      return false;
-+
-+    for (int pos = 0; pos < size; pos++)
-+      {
-+	if (!s.contains(itr.next()))
-+	  return false;
-+      }
-+    return true;
-   }
- 
--  /**
--   * Returns the value mapped by the given key. Returns <code>null</code> if
--   * there is no mapping.  However, in Maps that accept null values, you
--   * must rely on <code>containsKey</code> to determine if a mapping exists.
--   * This iteration takes linear time, searching entrySet().iterator() of
--   * the key.  Many implementations override this method.
--   *
--   * @param key the key to look up
--   * @return the value associated with the key, or null if key not in map
--   * @throws NullPointerException if this map does not accept null keys
--   * @see #containsKey(Object)
--   */
-   public Object get(Object key)
-   {
--    Iterator entries = entrySet().iterator();
--    int pos = size();
--    while (--pos >= 0)
-+    Set s = entrySet();
-+    Iterator entries = s.iterator();
-+    int size = size();
-+
-+    for (int pos = 0; pos < size; pos++)
-       {
--        Map.Entry entry = (Map.Entry) entries.next();
--        if (equals(key, entry.getKey()))
--          return entry.getValue();
-+	Map.Entry entry = (Map.Entry) entries.next();
-+	Object k = entry.getKey();
-+	if (key == null ? k == null : key.equals(k))
-+	  return entry.getValue();
-       }
-+
-     return null;
-   }
- 
--  /**
--   * Returns the hash code for this map. As defined in Map, this is the sum
--   * of all hashcodes for each Map.Entry object in entrySet, or basically
--   * entrySet().hashCode().
--   *
--   * @return the hash code
--   * @see Map.Entry#hashCode()
--   * @see Set#hashCode()
--   */
-   public int hashCode()
-   {
--    return entrySet().hashCode();
-+    int hashcode = 0;
-+    Iterator itr = entrySet().iterator();
-+    int size = size();
-+    for (int pos = 0; pos < size; pos++)
-+      {
-+	hashcode += itr.next().hashCode();
-+      }
-+    return hashcode;
-   }
- 
--  /**
--   * Returns true if the map contains no mappings. This is implemented by
--   * <code>size() == 0</code>.
--   *
--   * @return true if the map is empty
--   * @see #size()
--   */
-   public boolean isEmpty()
-   {
-     return size() == 0;
-   }
- 
--  /**
--   * Returns a set view of this map's keys. The set is backed by the map,
--   * so changes in one show up in the other. Modifications while an iteration
--   * is in progress produce undefined behavior. The set supports removal
--   * if entrySet() does, but does not support element addition.
--   * <p>
--   *
--   * This implementation creates an AbstractSet, where the iterator wraps
--   * the entrySet iterator, size defers to the Map's size, and contains
--   * defers to the Map's containsKey. The set is created on first use, and
--   * returned on subsequent uses, although since no synchronization occurs,
--   * there is a slight possibility of creating two sets.
--   *
--   * @return a Set view of the keys
--   * @see Set#iterator()
--   * @see #size()
--   * @see #containsKey(Object)
--   * @see #values()
--   */
-   public Set keySet()
-   {
--    if (keys == null)
--      keys = new AbstractSet()
-+    if (this.keySet == null)
-       {
--        public int size()
--        {
--          return AbstractMap.this.size();
--        }
--
--        public boolean contains(Object key)
--        {
--          return containsKey(key);
--        }
--
--        public Iterator iterator()
--        {
--          return new Iterator()
--          {
--            private final Iterator map_iterator = entrySet().iterator();
--
--            public boolean hasNext()
--            {
--              return map_iterator.hasNext();
--            }
--
--            public Object next()
--            {
--              return ((Map.Entry) map_iterator.next()).getKey();
--            }
--
--            public void remove()
--            {
--              map_iterator.remove();
--            }
--          };
--        }
--      };
--    return keys;
-+	this.keySet = new AbstractSet()
-+	{
-+	  public int size()
-+	  {
-+	    return AbstractMap.this.size();
-+	  }
-+
-+	  public boolean contains(Object key)
-+	  {
-+	    return AbstractMap.this.containsKey(key);
-+	  }
-+
-+	  public Iterator iterator()
-+	  {
-+	    return new Iterator()
-+	    {
-+	      Iterator map_iterator = AbstractMap.this.entrySet().iterator();
-+
-+	      public boolean hasNext()
-+	      {
-+		return map_iterator.hasNext();
-+	      }
-+
-+	      public Object next()
-+	      {
-+		return ((Map.Entry) map_iterator.next()).getKey();
-+	      }
-+
-+	      public void remove()
-+	      {
-+		map_iterator.remove();
-+	      }
-+	    };
-+	  }
-+	};
-+      }
-+
-+    return this.keySet;
-   }
- 
--  /**
--   * Associates the given key to the given value (optional operation). If the
--   * map already contains the key, its value is replaced. This implementation
--   * simply throws an UnsupportedOperationException. Be aware that in a map
--   * that permits <code>null</code> values, a null return does not always
--   * imply that the mapping was created.
--   *
--   * @param key the key to map
--   * @param value the value to be mapped
--   * @return the previous value of the key, or null if there was no mapping
--   * @throws UnsupportedOperationException if the operation is not supported
--   * @throws ClassCastException if the key or value is of the wrong type
--   * @throws IllegalArgumentException if something about this key or value
--   *         prevents it from existing in this map
--   * @throws NullPointerException if the map forbids null keys or values
--   * @see #containsKey(Object)
--   */
-   public Object put(Object key, Object value)
-   {
-     throw new UnsupportedOperationException();
-   }
- 
--  /**
--   * Copies all entries of the given map to this one (optional operation). If
--   * the map already contains a key, its value is replaced. This implementation
--   * simply iterates over the map's entrySet(), calling <code>put</code>,
--   * so it is not supported if puts are not.
--   *
--   * @param m the mapping to load into this map
--   * @throws UnsupportedOperationException if the operation is not supported
--   * @throws ClassCastException if a key or value is of the wrong type
--   * @throws IllegalArgumentException if something about a key or value
--   *         prevents it from existing in this map
--   * @throws NullPointerException if the map forbids null keys or values, or
--   *         if <code>m</code> is null.
--   * @see #put(Object, Object)
--   */
-   public void putAll(Map m)
-   {
-+    Map.Entry entry;
-     Iterator entries = m.entrySet().iterator();
--    int pos = size();
--    while (--pos >= 0)
-+    int size = m.size();
-+
-+    for (int pos = 0; pos < size; pos++)
-       {
--        Map.Entry entry = (Map.Entry) entries.next();
--        put(entry.getKey(), entry.getValue());
-+	entry = (Map.Entry) entries.next();
-+	put(entry.getKey(), entry.getValue());
-       }
-   }
- 
--  /**
--   * Removes the mapping for this key if present (optional operation). This
--   * implementation iterates over the entrySet searching for a matching
--   * key, at which point it calls the iterator's <code>remove</code> method.
--   * It returns the result of <code>getValue()</code> on the entry, if found,
--   * or null if no entry is found. Note that maps which permit null values
--   * may also return null if the key was removed.  If the entrySet does not
--   * support removal, this will also fail. This is O(n), so many
--   * implementations override it for efficiency.
--   *
--   * @param key the key to remove
--   * @return the value the key mapped to, or null if not present
--   * @throws UnsupportedOperationException if deletion is unsupported
--   * @see Iterator#remove()
--   */
-   public Object remove(Object key)
-   {
-     Iterator entries = entrySet().iterator();
--    int pos = size();
--    while (--pos >= 0)
-+    int size = size();
-+
-+    for (int pos = 0; pos < size; pos++)
-       {
--        Map.Entry entry = (Map.Entry) entries.next();
--        if (equals(key, entry.getKey()))
--          {
--            // Must get the value before we remove it from iterator.
--            Object r = entry.getValue();
--            entries.remove();
--            return r;
--          }
-+	Map.Entry entry = (Map.Entry) entries.next();
-+	Object k = entry.getKey();
-+	if (key == null ? k == null : key.equals(k))
-+	  {
-+	    Object value = entry.getValue();
-+	    entries.remove();
-+	    return value;
-+	  }
-       }
-+
-     return null;
-   }
- 
--  /**
--   * Returns the number of key-value mappings in the map. If there are more
--   * than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE. This is
--   * implemented as <code>entrySet().size()</code>.
--   *
--   * @return the number of mappings
--   * @see Set#size()
--   */
-   public int size()
-   {
-     return entrySet().size();
-   }
- 
--  /**
--   * Returns a String representation of this map. This is a listing of the
--   * map entries (which are specified in Map.Entry as being
--   * <code>getKey() + "=" + getValue()</code>), separated by a comma and
--   * space (", "), and surrounded by braces ('{' and '}'). This implementation
--   * uses a StringBuffer and iterates over the entrySet to build the String.
--   * Note that this can fail with an exception if underlying keys or
--   * values complete abruptly in toString().
--   *
--   * @return a String representation
--   * @see Map.Entry#toString()
--   */
-   public String toString()
-   {
-     Iterator entries = entrySet().iterator();
-+    int size = size();
-     StringBuffer r = new StringBuffer("{");
--    for (int pos = size(); pos > 0; pos--)
-+    for (int pos = 0; pos < size; pos++)
-       {
--        // Append the toString value of the entries rather than calling
--        // getKey/getValue. This is more efficient and it matches the JDK
--        // behaviour.
--        r.append(entries.next());
--        if (pos > 1)
--          r.append(", ");
-+        // Append the toString value of the entries rather than calling 
-+	// getKey/getValue. This is more efficient and it matches the JDK
-+	// behaviour.
-+	r.append(entries.next());	
-+	if (pos < size - 1)
-+	  r.append(", ");
-       }
-     r.append("}");
-     return r.toString();
-   }
- 
--  /**
--   * Returns a collection or bag view of this map's values. The collection
--   * is backed by the map, so changes in one show up in the other.
--   * Modifications while an iteration is in progress produce undefined
--   * behavior. The collection supports removal if entrySet() does, but
--   * does not support element addition.
--   * <p>
--   *
--   * This implementation creates an AbstractCollection, where the iterator
--   * wraps the entrySet iterator, size defers to the Map's size, and contains
--   * defers to the Map's containsValue. The collection is created on first
--   * use, and returned on subsequent uses, although since no synchronization
--   * occurs, there is a slight possibility of creating two collections.
--   *
--   * @return a Collection view of the values
--   * @see Collection#iterator()
--   * @see #size()
--   * @see #containsValue(Object)
--   * @see #keySet()
--   */
-   public Collection values()
-   {
--    if (values == null)
--      values = new AbstractCollection()
-+    if (this.valueCollection == null)
-       {
--        public int size()
--        {
--          return AbstractMap.this.size();
--        }
--
--        public Iterator iterator()
--        {
--          return new Iterator()
--          {
--            private final Iterator map_iterator = entrySet().iterator();
--
--            public boolean hasNext()
--            {
--              return map_iterator.hasNext();
--            }
--
--            public Object next()
--            {
--              return ((Map.Entry) map_iterator.next()).getValue();
--            }
--
--            public void remove()
--            {
--              map_iterator.remove();
--            }
--          };
--        }
--      };
--    return values;
--  }
-+	this.valueCollection = new AbstractCollection()
-+	{
-+	  public int size()
-+	  {
-+	    return AbstractMap.this.size();
-+	  }
-+
-+	  public Iterator iterator()
-+	  {
-+	    return new Iterator()
-+	    {
-+	      Iterator map_iterator = AbstractMap.this.entrySet().iterator();
-+
-+	      public boolean hasNext()
-+	      {
-+		return map_iterator.hasNext();
-+	      }
-+
-+	      public Object next()
-+	      {
-+		return ((Map.Entry) map_iterator.next()).getValue();
-+	      }
-+
-+	      public void remove()
-+	      {
-+		map_iterator.remove();
-+	      }
-+	    };
-+	  }
-+	};
-+      }
- 
--  /**
--   * Compare two objects according to Collection semantics.
--   *
--   * @param o1 the first object
--   * @param o2 the second object
--   * @return o1 == null ? o2 == null : o1.equals(o2)
--   */
--  // Package visible for use throughout java.util.
--  // It may be inlined since it is final.
--  static final boolean equals(Object o1, Object o2)
--  {
--    return o1 == null ? o2 == null : o1.equals(o2);
-+    return this.valueCollection;
-   }
- 
--  /**
--   * Hash an object according to Collection semantics.
--   *
--   * @param o the object to hash
--   * @return o1 == null ? 0 : o1.hashCode()
--   */
--  // Package visible for use throughout java.util.
--  // It may be inlined since it is final.
--  static final int hashCode(Object o)
--  {
--    return o == null ? 0 : o.hashCode();
--  }
-+  private Collection valueCollection = null;
-+  private Set keySet = null;
- }
++++ java/util/AbstractMap.java	Sat Dec 15 09:15:59 2001
+@@ -41,6 +41,7 @@
+  * efficient implementation.
+  *
+  * @author Original author unknown
++ * @author Bryce McKinlay
+  * @author Eric Blake <ebb9@email.byu.edu>
+  * @see Map
+  * @see Collection
Index: compare/java.util.AbstractSequentialList.diff
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/java/compare/java.util.AbstractSequentialList.diff,v
retrieving revision 1.1
diff -u -r1.1 java.util.AbstractSequentialList.diff
--- compare/java.util.AbstractSequentialList.diff 2001/11/07 01:23:48 1.1
+++ compare/java.util.AbstractSequentialList.diff 2001/12/16 00:14:00
@@ -1,243 +1,10 @@
 --- /home/tromey/gnu/egcs/classpath/classpath/java/util/AbstractSequentialList.java	Fri Oct 19 18:43:44 2001
-+++ java/util/AbstractSequentialList.java	Tue Oct 16 09:14:34 2001
-@@ -1,5 +1,5 @@
- /* AbstractSequentialList.java -- List implementation for sequential access
--   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
-+   Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
- 
- This file is part of GNU Classpath.
- 
-@@ -25,191 +25,100 @@
- executable file might be covered by the GNU General Public License. */
- 
- 
-+// TO DO:
-+// ~ Lots of doc comments still missing.
-+// ~ The class comment should include a description of what should be overridden
-+//   to provide what features, as should the listIterator comment.
-+
- package java.util;
- 
- /**
-  * Abstract superclass to make it easier to implement the List interface when
-- * backed by a sequential-access store, such as a linked list. For random
-- * access data, use AbstractList. This class implements the random access
-- * methods (<code>get</code>, <code>set</code>, <code>add</code>, and
-- * <code>remove</code>) atop the list iterator, opposite of AbstractList's
-- * approach of implementing the iterator atop random access.
-- * <p>
-- *
-- * To implement a list, you need an implementation for <code>size()</code>
-- * and <code>listIterator</code>.  With just <code>hasNext</code>,
-- * <code>next</code>, <code>hasPrevious</code>, <code>previous</code>,
-- * <code>nextIndex</code>, and <code>previousIndex</code>, you have an
-- * unmodifiable list. For a modifiable one, add <code>set</code>, and for
-- * a variable-size list, add <code>add</code> and <code>remove</code>.
-- * <p>
-- *
-- * The programmer should provide a no-argument constructor, and one that
-- * accepts another Collection, as recommended by the Collection interface.
-- * Unfortunately, there is no way to enforce this in Java.
-- *
-- * @author Original author unknown
-- * @author Eric Blake <ebb9@email.byu.edu>
-- * @see Collection
-- * @see List
-- * @see AbstractList
-- * @see AbstractCollection
-- * @see ListIterator
-- * @see LinkedList
-- * @since 1.2
-- * @status updated to 1.4
-+ * backed by a sequential-access store, such as a linked list.
-  */
- public abstract class AbstractSequentialList extends AbstractList
- {
-   /**
--   * The main constructor, for use by subclasses.
--   */
--  protected AbstractSequentialList()
--  {
--  }
--
--  /**
-    * Returns a ListIterator over the list, starting from position index.
-    * Subclasses must provide an implementation of this method.
-    *
--   * @param index the starting position of the list
--   * @return the list iterator
--   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
-+   * @exception IndexOutOfBoundsException if index < 0 || index > size()
-    */
-   public abstract ListIterator listIterator(int index);
- 
-   /**
--   * Insert an element into the list at a given position (optional operation).
--   * This shifts all existing elements from that position to the end one
--   * index to the right. This version of add has no return, since it is
--   * assumed to always succeed if there is no exception. This iteration
--   * uses listIterator(index).add(o).
--   *
--   * @param index the location to insert the item
--   * @param o the object to insert
--   * @throws UnsupportedOperationException if this list does not support the
--   *         add operation
--   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
--   * @throws ClassCastException if o cannot be added to this list due to its
--   *         type
--   * @throws IllegalArgumentException if o cannot be added to this list for
--   *         some other reason
-+   * Add an element to the list at a given index. This implementation obtains a
-+   * ListIterator positioned at the specified index, and then adds the element
-+   * using the ListIterator's add method.
-+   *
-+   * @param index the position to add the element
-+   * @param o the element to insert
-+   * @exception IndexOutOfBoundsException if index < 0 || index > size()
-+   * @exception UnsupportedOperationException if the iterator returned by
-+   *   listIterator(index) does not support the add method.
-    */
-   public void add(int index, Object o)
-   {
--    listIterator(index).add(o);
-+    ListIterator i = listIterator(index);
-+    i.add(o);
-   }
- 
-   /**
--   * Insert the contents of a collection into the list at a given position
--   * (optional operation). Shift all elements at that position to the right
--   * by the number of elements inserted. This operation is undefined if
--   * this list is modified during the operation (for example, if you try
--   * to insert a list into itself).
--   * <p>
--   *
--   * This implementation grabs listIterator(index), then proceeds to use add
--   * for each element returned by c's iterator. Sun's online specs are wrong,
--   * claiming that this also calls next(): listIterator.add() correctly
--   * skips the added element.
--   *
--   * @param index the location to insert the collection
--   * @param c the collection to insert
--   * @return true if the list was modified by this action, that is, if c is
--   *         non-empty
--   * @throws UnsupportedOperationException if this list does not support the
--   *         addAll operation
--   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
--   * @throws ClassCastException if some element of c cannot be added to this
--   *         list due to its type
--   * @throws IllegalArgumentException if some element of c cannot be added
--   *         to this list for some other reason
--   * @throws NullPointerException if the specified collection is null
--   * @see #add(int, Object)
-+   * @specnote The spec in the JDK1.3 online docs is wrong. The implementation
-+   *           should not call next() to skip over new elements as they are
-+   *           added, because iterator.add() should add new elements BEFORE
-+   *           the cursor.
-    */
-   public boolean addAll(int index, Collection c)
-   {
-+    boolean modified = false;
-     Iterator ci = c.iterator();
-     int size = c.size();
-     ListIterator i = listIterator(index);
--    for (int pos = size; pos > 0; pos--)
--      i.add(ci.next());
--    return size > 0;
-+    for (int pos = 0; pos < size; pos++)
-+      {
-+	i.add(ci.next());
-+      }
-+    return (size > 0);
-   }
- 
--  /**
--   * Get the element at a given index in this list. This implementation
--   * returns listIterator(index).next().
--   *
--   * @param index the index of the element to be returned
--   * @return the element at index index in this list
--   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
--   */
-   public Object get(int index)
-   {
--    // This is a legal listIterator position, but an illegal get.
--    if (index == size())
--      throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
--                                          + size());
--    return listIterator(index).next();
-+    ListIterator i = listIterator(index);
-+    if (index < 0 || index > size())
-+      throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + 
-+                                          size());
-+    return i.next();
-   }
- 
-   /**
--   * Obtain an Iterator over this list, whose sequence is the list order. This
--   * implementation returns listIterator().
-+   * Return an Iterator over this List. This implementation returns
-+   * listIterator().
-    *
--   * @return an Iterator over the elements of this list, in order
-+   * @return an Iterator over this List
-    */
-   public Iterator iterator()
-   {
-     return listIterator();
-   }
- 
--  /**
--   * Remove the element at a given position in this list (optional operation).
--   * Shifts all remaining elements to the left to fill the gap. This
--   * implementation uses listIterator(index) and ListIterator.remove().
--   *
--   * @param index the position within the list of the object to remove
--   * @return the object that was removed
--   * @throws UnsupportedOperationException if this list does not support the
--   *         remove operation
--   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
--   */
-   public Object remove(int index)
-   {
--    // This is a legal listIterator position, but an illegal remove.
--    if (index == size())
--      throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
--                                          + size());
-     ListIterator i = listIterator(index);
-+    if (index < 0 || index > size())
-+      throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + 
-+                                          size());
-     Object removed = i.next();
-     i.remove();
-     return removed;
-   }
- 
--  /**
--   * Replace an element of this list with another object (optional operation).
--   * This implementation uses listIterator(index) and ListIterator.set(o).
--   *
--   * @param index the position within this list of the element to be replaced
--   * @param o the object to replace it with
--   * @return the object that was replaced
--   * @throws UnsupportedOperationException if this list does not support the
--   *         set operation
--   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
--   * @throws ClassCastException if o cannot be added to this list due to its
--   *         type
--   * @throws IllegalArgumentException if o cannot be added to this list for
--   *         some other reason
--   */
-   public Object set(int index, Object o)
-   {
--    // This is a legal listIterator position, but an illegal set.
--    if (index == size())
--      throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
--                                          + size());
-     ListIterator i = listIterator(index);
-+    if (index < 0 || index > size())
-+      throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + 
-+                                          size());
-     Object old = i.next();
-     i.set(o);
-     return old;
++++ java/util/AbstractSequentialList.java	Sat Dec 15 09:15:59 2001
+@@ -49,6 +49,7 @@
+  * Unfortunately, there is no way to enforce this in Java.
+  *
+  * @author Original author unknown
++ * @author Bryce McKinlay
+  * @author Eric Blake <ebb9@email.byu.edu>
+  * @see Collection
+  * @see List
Index: compare/java.util.AbstractSet.diff
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/java/compare/java.util.AbstractSet.diff,v
retrieving revision 1.2
diff -u -r1.2 java.util.AbstractSet.diff
--- compare/java.util.AbstractSet.diff 2001/12/07 23:22:19 1.2
+++ compare/java.util.AbstractSet.diff 2001/12/16 00:14:00
@@ -1,106 +1,11 @@
 --- /home/tromey/gnu/egcs/classpath/classpath/java/util/AbstractSet.java	Sun Nov 25 12:30:06 2001
-+++ java/util/AbstractSet.java	Tue Oct 16 09:14:34 2001
-@@ -1,5 +1,5 @@
- /* AbstractSet.java -- Abstract implementation of most of Set
--   Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
-+   Copyright (C) 1998, 2000 Free Software Foundation, Inc.
- 
- This file is part of GNU Classpath.
- 
-@@ -35,28 +35,10 @@
-  * on them - specifically, no element may be in the set more than once). This
-  * class simply provides implementations of equals() and hashCode() to fulfil
-  * the requirements placed on them by the Set interface.
-- *
-- * @author Original author unknown
-- * @author Eric Blake <ebb9@email.byu.edu>
-- * @see Collection
-- * @see AbstractCollection
-- * @see Set
-- * @see HashSet
-- * @see TreeSet
-- * @see LinkedHashSet
-- * @since 1.2
-- * @status updated to 1.4
-  */
- public abstract class AbstractSet extends AbstractCollection implements Set
- {
-   /**
--   * The main constructor, for use by subclasses.
--   */
--  protected AbstractSet()
--  {
--  }
--
--  /**
-    * Tests whether the given object is equal to this Set. This implementation
-    * first checks whether this set <em>is</em> the given object, and returns
-    * true if so. Otherwise, if o is a Set and is the same size as this one, it
-@@ -68,9 +50,12 @@
-    */
-   public boolean equals(Object o)
-   {
--    return (o == this ||
--            (o instanceof Set && ((Set) o).size() == size()
--             && containsAll((Collection) o)));
-+    if (o == this)
-+      return true;
-+    else if (o instanceof Set && ((Set) o).size() == size())
-+      return containsAll((Collection) o);
-+    else
-+      return false;
-   }
- 
-   /**
-@@ -84,45 +69,14 @@
-   public int hashCode()
-   {
-     Iterator itr = iterator();
-+    int size = size();
-     int hash = 0;
--    int pos = size();
--    while (--pos >= 0)
--      hash += hashCode(itr.next());
--    return hash;
--  }
--
--  /**
--   * Removes from this set all elements in the given collection (optional
--   * operation). This implementation uses <code>size()</code> to determine
--   * the smaller collection.  Then, if this set is smaller, it iterates
--   * over the set, calling Iterator.remove if the collection contains
--   * the element.  If this set is larger, it iterates over the collection,
--   * calling Set.remove for all elements in the collection. Note that
--   * this operation will fail if a remove methods is not supported.
--   *
--   * @param c the collection of elements to remove
--   * @return true if the set was modified as a result
--   * @throws UnsupportedOperationException if remove is not supported
--   * @throws NullPointerException if the collection is null
--   * @see AbstractCollection#remove(Object)
--   * @see Collection#contains(Object)
--   * @see Iterator#remove()
--   */
--  public boolean removeAll(Collection c)
--  {
--    int oldsize = size();
--    int count = c.size();
--    Iterator i;
--    if (oldsize < count)
-+    for (int pos = 0; pos < size; pos++)
++++ java/util/AbstractSet.java	Sat Dec 15 09:15:59 2001
+@@ -115,7 +115,7 @@
+     Iterator i;
+     if (oldsize < count)
        {
 -        for (i = iterator(), count = oldsize; count > 0; count--)
--          if (c.contains(i.next()))
--            i.remove();
-+	Object obj = itr.next();
-+	if (obj != null)
-+	  hash += obj.hashCode();
++	for (i = iterator(), count = oldsize; count > 0; count--)
+           if (c.contains(i.next()))
+             i.remove();
        }
--    else
--      for (i = c.iterator(); count > 0; count--)
--        remove(i.next());
--    return oldsize != size();
-+    return hash;
-   }
--
- }
Index: compare/java.util.ArrayList.diff
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/java/compare/java.util.ArrayList.diff,v
retrieving revision 1.1
diff -u -r1.1 java.util.ArrayList.diff
--- compare/java.util.ArrayList.diff 2001/11/07 01:23:48 1.1
+++ compare/java.util.ArrayList.diff 2001/12/16 00:14:00
@@ -1,764 +1,28 @@
 --- /home/tromey/gnu/egcs/classpath/classpath/java/util/ArrayList.java	Fri Oct 26 16:06:57 2001
-+++ java/util/ArrayList.java	Tue Oct 16 09:14:34 2001
-@@ -1,6 +1,6 @@
- /* ArrayList.java -- JDK1.2's answer to Vector; this is an array-backed
-    implementation of the List interface
--   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
-+   Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
- 
- This file is part of GNU Classpath.
- 
-@@ -35,534 +35,383 @@
- import java.io.ObjectOutputStream;
- 
- /**
-- * An array-backed implementation of the List interface.  This implements
-- * all optional list operations, and permits null elements, so that it is
-- * better than Vector, which it replaces. Random access is roughly constant
-- * time, and iteration is roughly linear time, so it is nice and fast, with
-- * less overhead than a LinkedList.
-- * <p>
-+ * An array-backed implementation of the List interface.  ArrayList
-+ * performs well on simple tasks:  random access into a list, appending
-+ * to or removing from the end of a list, checking the size, &c.
++++ java/util/ArrayList.java	Sat Dec 15 09:15:59 2001
+@@ -60,6 +60,7 @@
+  * non-deterministic behavior.
   *
-- * Each list has a capacity, and as the array reaches that capacity it
-- * is automatically transferred to a larger array. You also have access to
-- * ensureCapacity and trimToSize to control the backing array's size, avoiding
-- * reallocation or wasted memory.
-- * <p>
-- *
-- * ArrayList is not synchronized, so if you need multi-threaded access,
-- * consider using:<br>
-- * <code>List l = Collections.synchronizedList(new ArrayList(...));</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
-- * {@link ConcurrentModificationException} rather than exhibit
-- * non-deterministic behavior.
-- *
-- * @author Jon A. Zeppieri
-- * @author Eric Blake <ebb9@email.byu.edu>
-- * @see Collection
-- * @see List
-- * @see LinkedList
-- * @see Vector
-- * @see Collections#synchronizedList(List)
-- * @see AbstractList
-- * @status updated to 1.4
-+ * @author        Jon A. Zeppieri
-+ * @see           java.util.AbstractList
-+ * @see           java.util.List
-  */
- public class ArrayList extends AbstractList
--  implements List, RandomAccess, Cloneable, Serializable
-+  implements List, Cloneable, Serializable
- {
--  /**
--   * Compatible with JDK 1.2
--   */
--  private static final long serialVersionUID = 8683452581122892189L;
--
--  /**
--   * The default capacity for new ArrayLists.
--   */
-+  /** the default capacity for new ArrayLists */
-   private static final int DEFAULT_CAPACITY = 16;
- 
--  /**
--   * The number of elements in this list.
--   * @serial the list size
--   */
--  private int size;
-+  /** the number of elements in this list */
-+  int size;
- 
--  /**
--   * Where the data is stored.
--   */
--  private transient Object[] data;
-+  /** where the data is stored */
-+  transient Object[] data;
- 
--  /**
--   * Construct a new ArrayList with the supplied initial capacity.
-+  /** 
-+   * Construct a new ArrayList with the supplied initial capacity. 
-    *
--   * @param capacity initial capacity of this ArrayList
--   * @throws IllegalArgumentException if capacity is negative
-+   * @param capacity Initial capacity of this ArrayList
-    */
-   public ArrayList(int capacity)
-   {
--    // Must explicitly check, to get correct exception.
--    if (capacity < 0)
--      throw new IllegalArgumentException();
-     data = new Object[capacity];
-   }
- 
-+
-   /**
--   * Construct a new ArrayList with the default capcity (16).
-+   * Construct a new ArrayList with the default capcity 
-    */
-   public ArrayList()
-   {
-     this(DEFAULT_CAPACITY);
-   }
- 
--  /**
-+  /** 
-    * Construct a new ArrayList, and initialize it with the elements
--   * in the supplied Collection. The initial capacity is 110% of the
--   * Collection's size.
-+   * in the supplied Collection; Sun specs say that the initial 
-+   * capacity is 110% of the Collection's size.
-    *
-    * @param c the collection whose elements will initialize this list
--   * @throws NullPointerException if c is null
-    */
-   public ArrayList(Collection c)
-   {
--    this((int) (c.size() * 1.1f));
-+    this((int) (c.size() * 1.1));
-     addAll(c);
-   }
- 
-   /**
--   * Trims the capacity of this List to be equal to its size;
--   * a memory saver.
--   */
--  public void trimToSize()
--  {
--    // Not a structural change from the perspective of iterators on this list,
--    // so don't update modCount.
--    if (size != data.length)
--      {
--        Object[] newData = new Object[size];
--        System.arraycopy(data, 0, newData, 0, size);
--        data = newData;
--      }
--  }
--
--  /**
-    * Guarantees that this list will have at least enough capacity to
--   * hold minCapacity elements. This implementation will grow the list to
--   * max(current * 2, minCapacity) if (minCapacity > current). The JCL says
--   * explictly that "this method increases its capacity to minCap", while
--   * the JDK 1.3 online docs specify that the list will grow to at least the
--   * size specified.
-+   * hold minCapacity elements. 
-    *
-+   * @specnote This implementation will grow the list to 
-+   *   max(current * 2, minCapacity) if (minCapacity > current). The JCL says
-+   *   explictly that "this method increases its capacity to minCap", while
-+   *   the JDK 1.3 online docs specify that the list will grow to at least the
-+   *   size specified.
-    * @param minCapacity the minimum guaranteed capacity
-    */
-   public void ensureCapacity(int minCapacity)
-   {
-+    Object[] newData;
-     int current = data.length;
- 
-     if (minCapacity > current)
-       {
--        Object[] newData = new Object[Math.max(current * 2, minCapacity)];
--        System.arraycopy(data, 0, newData, 0, size);
--        data = newData;
-+	newData = new Object[Math.max((current * 2), minCapacity)];
-+	System.arraycopy(data, 0, newData, 0, size);
-+	data = newData;
-       }
-   }
- 
-   /**
--   * Returns the number of elements in this list.
--   *
--   * @return the list size
--   */
--  public int size()
--  {
--    return size;
--  }
--
--  /**
--   * Checks if the list is empty.
-+   * Appends the supplied element to the end of this list.
-    *
--   * @return true if there are no elements
-+   * @param       e      the element to be appended to this list
-    */
--  public boolean isEmpty()
-+  public boolean add(Object e)
-   {
--    return size == 0;
-+    modCount++;
-+    if (size == data.length)
-+      ensureCapacity(size + 1);
-+    data[size++] = e;
-+    return true;
-   }
- 
-   /**
--   * Returns true iff element is in this ArrayList.
-+   * Retrieves the element at the user-supplied index.
-    *
--   * @param e the element whose inclusion in the List is being tested
--   * @return true if the list contains e
-+   * @param    index        the index of the element we are fetching
-+   * @throws   IndexOutOfBoundsException  (iIndex < 0) || (iIndex >= size())
-    */
--  public boolean contains(Object e)
-+  public Object get(int index)
-   {
--    return indexOf(e) != -1;
-+    if (index < 0 || index >= size)
-+      throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + 
-+                                          size);
-+    return data[index];
-   }
- 
-   /**
--   * Returns the lowest index at which element appears in this List, or
--   * -1 if it does not appear.
--   *
--   * @param e the element whose inclusion in the List is being tested
--   * @return the index where e was found
-+   * Returns the number of elements in this list 
-    */
--  public int indexOf(Object e)
-+  public int size()
-   {
--    for (int i = 0; i < size; i++)
--      if (equals(e, data[i]))
--        return i;
--    return -1;
-+    return size;
-   }
- 
-   /**
--   * Returns the highest index at which element appears in this List, or
--   * -1 if it does not appear.
-+   * Removes the element at the user-supplied index
-    *
--   * @param e the element whose inclusion in the List is being tested
--   * @return the index where e was found
-+   * @param     iIndex      the index of the element to be removed
-+   * @return    the removed Object
-+   * @throws    IndexOutOfBoundsException  (iIndex < 0) || (iIndex >= size())
-    */
--  public int lastIndexOf(Object e)
-+  public Object remove(int index)
-   {
--    for (int i = size - 1; i >= 0; i--)
--      if (equals(e, data[i]))
--        return i;
--    return -1;
-+    modCount++;
-+    if (index < 0 || index > size)
-+      throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + 
-+                                          size);
-+    Object r = data[index];
-+    if (index != --size)
-+      System.arraycopy(data, (index + 1), data, index, (size - index));
-+    data[size] = null;
-+    return r;
-   }
- 
-   /**
--   * Creates a shallow copy of this ArrayList (elements are not cloned).
-+   * Removes all elements in the half-open interval [iFromIndex, iToIndex).
-    *
--   * @return the cloned object
-+   * @param     fromIndex   the first index which will be removed
-+   * @param     toIndex     one greater than the last index which will be 
-+   *                         removed
-    */
--  public Object clone()
-+  protected void removeRange(int fromIndex, int toIndex)
-   {
--    ArrayList clone = null;
--    try
--      {
--        clone = (ArrayList) super.clone();
--        clone.data = (Object[]) data.clone();
--      }
--    catch (CloneNotSupportedException e)
-+    modCount++;
-+    if (fromIndex != toIndex)
-       {
--        // Impossible to get here.
-+	System.arraycopy(data, toIndex, data, fromIndex, size - toIndex);
-+	size -= (toIndex - fromIndex);
-       }
--    return clone;
--  }
--
--  /**
--   * Returns an Object array containing all of the elements in this ArrayList.
--   * The array is independent of this list.
--   *
--   * @return an array representation of this list
--   */
--  public Object[] toArray()
--  {
--    Object[] array = new Object[size];
--    System.arraycopy(data, 0, array, 0, size);
--    return array;
--  }
--
--  /**
--   * Returns an Array whose component type is the runtime component type of
--   * the passed-in Array.  The returned Array is populated with all of the
--   * elements in this ArrayList.  If the passed-in Array is not large enough
--   * to store all of the elements in this List, a new Array will be created
--   * and returned; if the passed-in Array is <i>larger</i> than the size
--   * of this List, then size() index will be set to null.
--   *
--   * @param a the passed-in Array
--   * @return an array representation of this list
--   * @throws ArrayStoreException if the runtime type of a does not allow
--   *         an element in this list
--   * @throws NullPointerException if a is null
--   */
--  public Object[] toArray(Object[] a)
--  {
--    if (a.length < size)
--      a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
--                                       size);
--    else if (a.length > size)
--      a[size] = null;
--    System.arraycopy(data, 0, a, 0, size);
--    return a;
--  }
--
--  /**
--   * Retrieves the element at the user-supplied index.
--   *
--   * @param index the index of the element we are fetching
--   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
--   */
--  public Object get(int index)
--  {
--    checkBoundExclusive(index);
--    return data[index];
--  }
--
--  /**
--   * Sets the element at the specified index.
--   *
--   * @param index the index at which the element is being set
--   * @param e the element to be set
--   * @return the element previously at the specified index
--   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= 0
--   */
--  public Object set(int index, Object e)
--  {
--    checkBoundExclusive(index);
--    Object result = data[index];
--    data[index] = e;
--    return result;
--  }
--
--  /**
--   * Appends the supplied element to the end of this list.
--   *
--   * @param e the element to be appended to this list
--   * @return true, the add will always succeed
--   */
--  public boolean add(Object e)
--  {
--    modCount++;
--    if (size == data.length)
--      ensureCapacity(size + 1);
--    data[size++] = e;
--    return true;
-   }
- 
-   /**
-    * Adds the supplied element at the specified index, shifting all
-    * elements currently at that index or higher one to the right.
-    *
--   * @param index the index at which the element is being added
--   * @param e the item being added
--   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
-+   * @param     index      the index at which the element is being added
-+   * @param     e          the item being added
-    */
-   public void add(int index, Object e)
-   {
--    checkBoundInclusive(index);
-     modCount++;
-+    if (index < 0 || index > size)
-+      throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + 
-+                                          size);
-     if (size == data.length)
-       ensureCapacity(size + 1);
-     if (index != size)
--      System.arraycopy(data, index, data, index + 1, size - index);
-+      System.arraycopy(data, index, data, index + 1, size - index);    
-     data[index] = e;
-     size++;
-   }
- 
--  /**
--   * Removes the element at the user-supplied index.
-+  /** 
-+   * Add each element in the supplied Collection to this List.
-    *
--   * @param index the index of the element to be removed
--   * @return the removed Object
--   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
--   */
--  public Object remove(int index)
--  {
--    checkBoundExclusive(index);
--    Object r = data[index];
--    modCount++;
--    if (index != --size)
--      System.arraycopy(data, index + 1, data, index, size - index);
--    // Aid for garbage collection by releasing this pointer.
--    data[size] = null;
--    return r;
--  }
--
--  /**
--   * Removes all elements from this List
--   */
--  public void clear()
--  {
--    if (size > 0)
--      {
--        modCount++;
--        // Allow for garbage collection.
--        Arrays.fill(data, 0, size, null);
--        size = 0;
--      }
--  }
--
--  /**
--   * Add each element in the supplied Collection to this List. It is undefined
--   * what happens if you modify the list while this is taking place; for
--   * example, if the collection contains this list.
--   *
--   * @param c a Collection containing elements to be added to this List
--   * @return true if the list was modified, in other words c is not empty
--   * @throws NullPointerException if c is null
-+   * @param        c          a Collection containing elements to be 
-+   *                          added to this List
-    */
-   public boolean addAll(Collection c)
-   {
-     return addAll(size, c);
-   }
- 
--  /**
-+  /** 
-    * Add all elements in the supplied collection, inserting them beginning
-    * at the specified index.
-    *
--   * @param index the index at which the elements will be inserted
--   * @param c the Collection containing the elements to be inserted
--   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; 0
--   * @throws NullPointerException if c is null
-+   * @param     index       the index at which the elements will be inserted
-+   * @param     c           the Collection containing the elements to be
-+   *                        inserted
-    */
-   public boolean addAll(int index, Collection c)
-   {
--    checkBoundInclusive(index);
-+    if (index < 0 || index > size)
-+      throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + 
-+                                          size);
-+    modCount++;
-     Iterator itr = c.iterator();
-     int csize = c.size();
- 
--    modCount++;
-     if (csize + size > data.length)
-       ensureCapacity(size + csize);
-     int end = index + csize;
--    if (index != size)
-+    if (size > 0 && index != size)
-       System.arraycopy(data, index, data, end, csize);
-     size += csize;
--    for ( ; index < end; index++)
--      data[index] = itr.next();
--    return csize > 0;
-+    for (; index < end; index++)
-+      {
-+        data[index] = itr.next();
-+      }
-+    return (csize > 0);
-   }
- 
-   /**
--   * Removes all elements in the half-open interval [fromIndex, toIndex).
--   * You asked for it if you call this with invalid arguments.
--   *
--   * @param fromIndex the first index which will be removed
--   * @param toIndex one greater than the last index which will be removed
-+   * Creates a shallow copy of this ArrayList
-    */
--  protected void removeRange(int fromIndex, int toIndex)
-+  public Object clone()
-   {
--    if (fromIndex != toIndex)
-+    ArrayList clone = null;
-+    try
-       {
--        modCount++;
--        System.arraycopy(data, toIndex, data, fromIndex, size - toIndex);
--        size -= toIndex - fromIndex;
-+	clone = (ArrayList) super.clone();
-+	clone.data = new Object[data.length];
-+	System.arraycopy(data, 0, clone.data, 0, size);
-       }
-+    catch (CloneNotSupportedException e) {}
-+    return clone;
-   }
- 
--  /**
--   * Checks that the index is in the range of possible elements (inclusive).
-+  /** 
-+   * Returns true iff oElement is in this ArrayList.
-    *
--   * @param index the index to check
--   * @throws IndexOutOfBoundsException if index &gt; size
-+   * @param     e     the element whose inclusion in the List is being
-+   *                  tested
-    */
--  private void checkBoundInclusive(int index)
-+  public boolean contains(Object e)
-   {
--    // Implementation note: we do not check for negative ranges here, since
--    // use of a negative index will cause an ArrayIndexOutOfBoundsException,
--    // a subclass of the required exception, with no effort on our part.
--    if (index > size)
+  * @author Jon A. Zeppieri
++ * @author Bryce McKinlay
+  * @author Eric Blake <ebb9@email.byu.edu>
+  * @see Collection
+  * @see List
+@@ -452,7 +453,7 @@
+     // use of a negative index will cause an ArrayIndexOutOfBoundsException,
+     // a subclass of the required exception, with no effort on our part.
+     if (index > size)
 -      throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
--                                          + size);
-+    return (indexOf(e) != -1);
++      throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+                                           + size);
    }
  
-   /**
--   * Checks that the index is in the range of existing elements (exclusive).
-+   * Returns the lowest index at which oElement appears in this List, or 
-+   * -1 if it does not appear.
-    *
--   * @param index the index to check
--   * @throws IndexOutOfBoundsException if index &gt;= size
-+   * @param    e       the element whose inclusion in the List is being
-+   *                   tested
-    */
--  private void checkBoundExclusive(int index)
-+  public int indexOf(Object e)
-   {
--    // Implementation note: we do not check for negative ranges here, since
--    // use of a negative index will cause an ArrayIndexOutOfBoundsException,
--    // a subclass of the required exception, with no effort on our part.
--    if (index >= size)
+@@ -468,7 +469,7 @@
+     // use of a negative index will cause an ArrayIndexOutOfBoundsException,
+     // a subclass of the required exception, with no effort on our part.
+     if (index >= size)
 -      throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
--                                          + size);
-+    for (int i = 0; i < size; i++)
-+      {
-+	if (e == null ? data[i] == null : e.equals(data[i]))
-+	  return i;
-+      }
-+    return -1;
-   }
- 
-   /**
--   * Remove from this list all elements contained in the given collection.
--   * This is not public, due to Sun's API, but this performs in linear
--   * time while the default behavior of AbstractList would be quadratic.
-+   * Returns the highest index at which oElement appears in this List, or 
-+   * -1 if it does not appear.
-    *
--   * @param c the collection to filter out
--   * @return true if this list changed
--   * @throws NullPointerException if c is null
-+   * @param    e       the element whose inclusion in the List is being
-+   *                   tested
-    */
--  boolean removeAllInternal(Collection c)
-+  public int lastIndexOf(Object e)
-   {
-     int i;
--    int j;
--    for (i = 0; i < size; i++)
--      if (c.contains(data[i]))
--        break;
--    if (i == size)
--      return false;
- 
--    modCount++;
--    for (j = i++; i < size; i++)
--      if (! c.contains(data[i]))
--        data[j++] = data[i];
--    size -= i - j;
--    return true;
-+    for (i = size - 1; i >= 0; i--)
-+      {
-+	if (e == null ? data[i] == null : e.equals(data[i]))
-+	  return i;
-+      }
-+    return -1;
++      throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+                                           + size);
    }
  
-   /**
--   * Retain in this vector only the elements contained in the given collection.
--   * This is not public, due to Sun's API, but this performs in linear
--   * time while the default behavior of AbstractList would be quadratic.
--   *
--   * @param c the collection to filter by
--   * @return true if this vector changed
--   * @throws NullPointerException if c is null
--   * @since 1.2
-+   * Removes all elements from this List
-    */
--  boolean retainAllInternal(Collection c)
-+  public void clear()
-   {
--    int i;
--    int j;
--    for (i = 0; i < size; i++)
--      if (! c.contains(data[i]))
--        break;
--    if (i == size)
--      return false;
--
-     modCount++;
--    for (j = i++; i < size; i++)
--      if (c.contains(data[i]))
--        data[j++] = data[i];
--    size -= i - j;
--    return true;
-+    for (int i = 0; i < size; i++)
-+      {
-+	data[i] = null;
-+      }    
-+    size = 0;
-   }
- 
-   /**
--   * Serializes this object to the given stream.
-+   * Sets the element at the specified index.
-    *
--   * @param out the stream to write to
--   * @throws IOException if the underlying stream fails
--   * @serialData the size field (int), the length of the backing array
--   *             (int), followed by its elements (Objects) in proper order.
-+   * @param     index   the index at which the element is being set
-+   * @param     e       the element to be set
-+   * @return    the element previously at the specified index, or null if
-+   *            none was there
-    */
--  private void writeObject(ObjectOutputStream s) throws IOException
-+  public Object set(int index, Object e)
-   {
--    // The 'size' field.
--    s.defaultWriteObject();
--    // We serialize unused list entries to preserve capacity.
--    int len = data.length;
--    s.writeInt(len);
--    for (int i = 0; i < len; i++)
--      s.writeObject(data[i]);
-+    Object result;
-+    if (index < 0 || index >= size)
-+      throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + 
-+                                          size);
-+    result = data[index];
-+    // SEH: no structural change, so don't update modCount
-+    data[index] = e;
-+    return result;
-   }
- 
-   /**
--   * Deserializes this object from the given stream.
-+   * Returns an Object Array containing all of the elements in this ArrayList
-+   */
-+  public Object[] toArray()
-+  {
-+    Object[] array = new Object[size];
-+    System.arraycopy(data, 0, array, 0, size);
-+    return array;
-+  }
-+
-+  /**
-+   * Returns an Array whose component type is the runtime component type of
-+   * the passed-in Array.  The returned Array is populated with all of the
-+   * elements in this ArrayList.  If the passed-in Array is not large enough
-+   * to store all of the elements in this List, a new Array will be created 
-+   * and returned; if the passed-in Array is <i>larger</i> than the size
-+   * of this List, then size() index will be set to null.
-    *
--   * @param in the stream to read from
--   * @throws ClassNotFoundException if the underlying stream fails
--   * @throws IOException if the underlying stream fails
--   * @serialData the size field (int), the length of the backing array
--   *             (int), followed by its elements (Objects) in proper order.
-+   * @param      array      the passed-in Array
-    */
--  private void readObject(ObjectInputStream s)
-+  public Object[] toArray(Object[] array)
-+  {
-+    if (array.length < size)
-+      array = (Object[]) Array.newInstance(array.getClass().getComponentType(), 
-+        				   size);
-+    else if (array.length > size)
-+      array[size] = null;
-+    System.arraycopy(data, 0, array, 0, size);
-+    return array;
-+  }
-+
-+  /**
-+   * Trims the capacity of this List to be equal to its size; 
-+   * a memory saver.   
-+   */
-+  public void trimToSize()
-+  {
-+    // not a structural change from the perspective of iterators on this list, 
-+    // so don't update modCount
-+    Object[] newData = new Object[size];
-+    System.arraycopy(data, 0, newData, 0, size);
-+    data = newData;
-+  }
-+
-+  private void writeObject(ObjectOutputStream out) throws IOException
-+  {
-+    int i;
-+
-+    // The 'size' field.
-+    out.defaultWriteObject();
-+
-+    // FIXME: Do we really want to serialize unused list entries??
-+    out.writeInt(data.length);
-+    for (i = 0; i < data.length; i++)
-+      out.writeObject(data[i]);
-+  }
-+
-+  private void readObject(ObjectInputStream in)
-     throws IOException, ClassNotFoundException
-   {
-+    int i;
-+    int capacity;
-+
-     // the `size' field.
--    s.defaultReadObject();
--    int capacity = s.readInt();
-+    in.defaultReadObject();
-+
-+    capacity = in.readInt();
-     data = new Object[capacity];
--    for (int i = 0; i < capacity; i++)
--      data[i] = s.readObject();
-+
-+    for (i = 0; i < capacity; i++)
-+      data[i] = in.readObject();
-   }
- }
Index: compare/java.util.Arrays.diff
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/java/compare/java.util.Arrays.diff,v
retrieving revision 1.1
diff -u -r1.1 java.util.Arrays.diff
--- compare/java.util.Arrays.diff 2001/11/07 01:23:48 1.1
+++ compare/java.util.Arrays.diff 2001/12/16 00:14:00
@@ -1,3657 +1,19 @@
 --- /home/tromey/gnu/egcs/classpath/classpath/java/util/Arrays.java	Fri Oct 26 16:06:57 2001
-+++ java/util/Arrays.java	Tue Oct 16 09:14:34 2001
-@@ -1,5 +1,5 @@
- /* Arrays.java -- Utility class with methods to operate on arrays
--   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
-+   Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
- 
- This file is part of GNU Classpath.
- 
-@@ -25,32 +25,16 @@
- executable file might be covered by the GNU General Public License. */
- 
- 
--package java.util;
-+// TO DO:
-+// ~ Fix the behaviour of sort and binarySearch as applied to float and double
-+//   arrays containing NaN values. See the JDC, bug ID 4143272.
- 
--import java.io.Serializable;
--import java.lang.reflect.Array;
-+package java.util;
- 
- /**
-  * This class contains various static utility methods performing operations on
-  * arrays, and a method to provide a List "view" of an array to facilitate
-- * using arrays with Collection-based APIs. All methods throw a
-- * {@link NullPointerException} if the parameter array is null.
-- * <p>
-- *
-- * Implementations may use their own algorithms, but must obey the general
-- * properties; for example, the sort must be stable and n*log(n) complexity.
-- * Sun's implementation of sort, and therefore ours, is a tuned quicksort,
-- * adapted from Jon L. Bentley and M. Douglas McIlroy's "Engineering a Sort
-- * Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265
-- * (November 1993). This algorithm offers n*log(n) performance on many data
-- * sets that cause other quicksorts to degrade to quadratic performance.
-- *
-- * @author Original author unknown
-- * @author Eric Blake <ebb9@email.byu.edu>
-- * @see Comparable
-- * @see Comparator
-- * @since 1.2
-- * @status updated to 1.4
-+ * using arrays with Collection-based APIs.
-  */
- public class Arrays
- {
-@@ -61,8 +45,14 @@
-   {
-   }
- 
--
--// binarySearch
-+  private static Comparator defaultComparator = new Comparator()
-+  {
-+    public int compare(Object o1, Object o2)
-+    {
-+      return ((Comparable) o1).compareTo(o2);
-+    }
-+  };
-+
-   /**
-    * Perform a binary search of a byte array for a key. The array must be
-    * sorted (as by the sort() method) - if it is not, the behaviour of this
-@@ -73,26 +63,32 @@
-    *
-    * @param a the array to search (must be sorted)
-    * @param key the value to search for
--   * @return the index at which the key was found, or -n-1 if it was not
--   *         found, where n is the index of the first value higher than key or
--   *         a.length if there is no such value.
-+   * @returns the index at which the key was found, or -n-1 if it was not
-+   *   found, where n is the index of the first value higher than key or
-+   *   a.length if there is no such value.
-    */
--  public static int binarySearch(byte[] a, byte key)
-+  public static int binarySearch(byte[]a, byte key)
-   {
-     int low = 0;
-     int hi = a.length - 1;
-     int mid = 0;
-     while (low <= hi)
-       {
--        mid = (low + hi) >> 1;
--        final byte d = a[mid];
--        if (d == key)
--          return mid;
--        else if (d > key)
--          hi = mid - 1;
--        else
--          // This gets the insertion point right on the last loop.
--          low = ++mid;
-+	mid = (low + hi) >> 1;
-+	final byte d = a[mid];
-+	if (d == key)
-+	  {
-+	    return mid;
-+	  }
-+	else if (d > key)
-+	  {
-+	    hi = mid - 1;
-+	  }
-+	else
-+	  {
-+	    // This gets the insertion point right on the last loop
-+	    low = ++mid;
-+	  }
-       }
-     return -mid - 1;
-   }
-@@ -107,32 +103,38 @@
-    *
-    * @param a the array to search (must be sorted)
-    * @param key the value to search for
--   * @return the index at which the key was found, or -n-1 if it was not
--   *         found, where n is the index of the first value higher than key or
--   *         a.length if there is no such value.
-+   * @returns the index at which the key was found, or -n-1 if it was not
-+   *   found, where n is the index of the first value higher than key or
-+   *   a.length if there is no such value.
-    */
--  public static int binarySearch(char[] a, char key)
-+  public static int binarySearch(char[]a, char key)
-   {
-     int low = 0;
-     int hi = a.length - 1;
-     int mid = 0;
-     while (low <= hi)
-       {
--        mid = (low + hi) >> 1;
--        final char d = a[mid];
--        if (d == key)
--          return mid;
--        else if (d > key)
--          hi = mid - 1;
--        else
--          // This gets the insertion point right on the last loop.
--          low = ++mid;
-+	mid = (low + hi) >> 1;
-+	final char d = a[mid];
-+	if (d == key)
-+	  {
-+	    return mid;
-+	  }
-+	else if (d > key)
-+	  {
-+	    hi = mid - 1;
-+	  }
-+	else
-+	  {
-+	    // This gets the insertion point right on the last loop
-+	    low = ++mid;
-+	  }
-       }
-     return -mid - 1;
-   }
- 
-   /**
--   * Perform a binary search of a short array for a key. The array must be
-+   * Perform a binary search of a double array for a key. The array must be
-    * sorted (as by the sort() method) - if it is not, the behaviour of this
-    * method is undefined, and may be an infinite loop. If the array contains
-    * the key more than once, any one of them may be found. Note: although the
-@@ -141,32 +143,38 @@
-    *
-    * @param a the array to search (must be sorted)
-    * @param key the value to search for
--   * @return the index at which the key was found, or -n-1 if it was not
--   *         found, where n is the index of the first value higher than key or
--   *         a.length if there is no such value.
-+   * @returns the index at which the key was found, or -n-1 if it was not
-+   *   found, where n is the index of the first value higher than key or
-+   *   a.length if there is no such value.
-    */
--  public static int binarySearch(short[] a, short key)
-+  public static int binarySearch(double[]a, double key)
-   {
-     int low = 0;
-     int hi = a.length - 1;
-     int mid = 0;
-     while (low <= hi)
-       {
--        mid = (low + hi) >> 1;
--        final short d = a[mid];
--        if (d == key)
--          return mid;
--        else if (d > key)
--          hi = mid - 1;
--        else
--          // This gets the insertion point right on the last loop.
--          low = ++mid;
-+	mid = (low + hi) >> 1;
-+	final double d = a[mid];
-+	if (d == key)
-+	  {
-+	    return mid;
-+	  }
-+	else if (d > key)
-+	  {
-+	    hi = mid - 1;
-+	  }
-+	else
-+	  {
-+	    // This gets the insertion point right on the last loop
-+	    low = ++mid;
-+	  }
-       }
-     return -mid - 1;
-   }
- 
-   /**
--   * Perform a binary search of an int array for a key. The array must be
-+   * Perform a binary search of a float array for a key. The array must be
-    * sorted (as by the sort() method) - if it is not, the behaviour of this
-    * method is undefined, and may be an infinite loop. If the array contains
-    * the key more than once, any one of them may be found. Note: although the
-@@ -175,32 +183,38 @@
-    *
-    * @param a the array to search (must be sorted)
-    * @param key the value to search for
--   * @return the index at which the key was found, or -n-1 if it was not
--   *         found, where n is the index of the first value higher than key or
--   *         a.length if there is no such value.
-+   * @returns the index at which the key was found, or -n-1 if it was not
-+   *   found, where n is the index of the first value higher than key or
-+   *   a.length if there is no such value.
-    */
--  public static int binarySearch(int[] a, int key)
-+  public static int binarySearch(float[]a, float key)
-   {
-     int low = 0;
-     int hi = a.length - 1;
-     int mid = 0;
-     while (low <= hi)
-       {
--        mid = (low + hi) >> 1;
--        final int d = a[mid];
--        if (d == key)
--          return mid;
--        else if (d > key)
--          hi = mid - 1;
--        else
--          // This gets the insertion point right on the last loop.
--          low = ++mid;
-+	mid = (low + hi) >> 1;
-+	final float d = a[mid];
-+	if (d == key)
-+	  {
-+	    return mid;
-+	  }
-+	else if (d > key)
-+	  {
-+	    hi = mid - 1;
-+	  }
-+	else
-+	  {
-+	    // This gets the insertion point right on the last loop
-+	    low = ++mid;
-+	  }
-       }
-     return -mid - 1;
-   }
- 
-   /**
--   * Perform a binary search of a long array for a key. The array must be
-+   * Perform a binary search of an int array for a key. The array must be
-    * sorted (as by the sort() method) - if it is not, the behaviour of this
-    * method is undefined, and may be an infinite loop. If the array contains
-    * the key more than once, any one of them may be found. Note: although the
-@@ -209,32 +223,38 @@
-    *
-    * @param a the array to search (must be sorted)
-    * @param key the value to search for
--   * @return the index at which the key was found, or -n-1 if it was not
--   *         found, where n is the index of the first value higher than key or
--   *         a.length if there is no such value.
-+   * @returns the index at which the key was found, or -n-1 if it was not
-+   *   found, where n is the index of the first value higher than key or
-+   *   a.length if there is no such value.
-    */
--  public static int binarySearch(long[] a, long key)
-+  public static int binarySearch(int[]a, int key)
-   {
-     int low = 0;
-     int hi = a.length - 1;
-     int mid = 0;
-     while (low <= hi)
-       {
--        mid = (low + hi) >> 1;
--        final long d = a[mid];
--        if (d == key)
--          return mid;
--        else if (d > key)
--          hi = mid - 1;
--        else
--          // This gets the insertion point right on the last loop.
--          low = ++mid;
-+	mid = (low + hi) >> 1;
-+	final int d = a[mid];
-+	if (d == key)
-+	  {
-+	    return mid;
-+	  }
-+	else if (d > key)
-+	  {
-+	    hi = mid - 1;
-+	  }
-+	else
-+	  {
-+	    // This gets the insertion point right on the last loop
-+	    low = ++mid;
-+	  }
-       }
-     return -mid - 1;
-   }
- 
-   /**
--   * Perform a binary search of a float array for a key. The array must be
-+   * Perform a binary search of a long array for a key. The array must be
-    * sorted (as by the sort() method) - if it is not, the behaviour of this
-    * method is undefined, and may be an infinite loop. If the array contains
-    * the key more than once, any one of them may be found. Note: although the
-@@ -243,33 +263,38 @@
-    *
-    * @param a the array to search (must be sorted)
-    * @param key the value to search for
--   * @return the index at which the key was found, or -n-1 if it was not
--   *         found, where n is the index of the first value higher than key or
--   *         a.length if there is no such value.
-+   * @returns the index at which the key was found, or -n-1 if it was not
-+   *   found, where n is the index of the first value higher than key or
-+   *   a.length if there is no such value.
-    */
--  public static int binarySearch(float[] a, float key)
-+  public static int binarySearch(long[]a, long key)
-   {
--    // Must use Float.compare to take into account NaN, +-0.
-     int low = 0;
-     int hi = a.length - 1;
-     int mid = 0;
-     while (low <= hi)
-       {
--        mid = (low + hi) >> 1;
--        final int r = Float.compare(a[mid], key);
--        if (r == 0)
--          return mid;
--        else if (r > 0)
--          hi = mid - 1;
--        else
--          // This gets the insertion point right on the last loop
--          low = ++mid;
-+	mid = (low + hi) >> 1;
-+	final long d = a[mid];
-+	if (d == key)
-+	  {
-+	    return mid;
-+	  }
-+	else if (d > key)
-+	  {
-+	    hi = mid - 1;
-+	  }
-+	else
-+	  {
-+	    // This gets the insertion point right on the last loop
-+	    low = ++mid;
-+	  }
-       }
-     return -mid - 1;
-   }
- 
-   /**
--   * Perform a binary search of a double array for a key. The array must be
-+   * Perform a binary search of a short array for a key. The array must be
-    * sorted (as by the sort() method) - if it is not, the behaviour of this
-    * method is undefined, and may be an infinite loop. If the array contains
-    * the key more than once, any one of them may be found. Note: although the
-@@ -278,27 +303,63 @@
-    *
-    * @param a the array to search (must be sorted)
-    * @param key the value to search for
--   * @return the index at which the key was found, or -n-1 if it was not
--   *         found, where n is the index of the first value higher than key or
--   *         a.length if there is no such value.
-+   * @returns the index at which the key was found, or -n-1 if it was not
-+   *   found, where n is the index of the first value higher than key or
-+   *   a.length if there is no such value.
-    */
--  public static int binarySearch(double[] a, double key)
-+  public static int binarySearch(short[]a, short key)
-   {
--    // Must use Double.compare to take into account NaN, +-0.
-     int low = 0;
-     int hi = a.length - 1;
-     int mid = 0;
-     while (low <= hi)
-       {
--        mid = (low + hi) >> 1;
--        final int r = Double.compare(a[mid], key);
--        if (r == 0)
--          return mid;
--        else if (r > 0)
--          hi = mid - 1;
--        else
--          // This gets the insertion point right on the last loop
--          low = ++mid;
-+	mid = (low + hi) >> 1;
-+	final short d = a[mid];
-+	if (d == key)
-+	  {
-+	    return mid;
-+	  }
-+	else if (d > key)
-+	  {
-+	    hi = mid - 1;
-+	  }
-+	else
-+	  {
-+	    // This gets the insertion point right on the last loop
-+	    low = ++mid;
-+	  }
-+      }
-+    return -mid - 1;
-+  }
-+
-+  /**
-+   * This method does the work for the Object binary search methods. 
-+   * @exception NullPointerException if the specified comparator is null.
-+   * @exception ClassCastException if the objects are not comparable by c.
-+   */
-+  private static int objectSearch(Object[]a, Object key, final Comparator c)
-+  {
-+    int low = 0;
-+    int hi = a.length - 1;
-+    int mid = 0;
-+    while (low <= hi)
-+      {
-+	mid = (low + hi) >> 1;
-+	final int d = c.compare(key, a[mid]);
-+	if (d == 0)
-+	  {
-+	    return mid;
-+	  }
-+	else if (d < 0)
-+	  {
-+	    hi = mid - 1;
-+	  }
-+	else
-+	  {
-+	    // This gets the insertion point right on the last loop
-+	    low = ++mid;
-+	  }	    
++++ java/util/Arrays.java	Sat Dec 15 09:16:00 2001
+@@ -46,6 +46,7 @@
+  * sets that cause other quicksorts to degrade to quadratic performance.
+  *
+  * @author Original author unknown
++ * @author Bryce McKinlay
+  * @author Eric Blake <ebb9@email.byu.edu>
+  * @see Comparable
+  * @see Comparator
+@@ -2334,8 +2335,6 @@
        }
-     return -mid - 1;
-   }
-@@ -315,16 +376,16 @@
-    *
-    * @param a the array to search (must be sorted)
-    * @param key the value to search for
--   * @return the index at which the key was found, or -n-1 if it was not
--   *         found, where n is the index of the first value higher than key or
--   *         a.length if there is no such value.
--   * @throws ClassCastException if key could not be compared with one of the
--   *         elements of a
--   * @throws NullPointerException if a null element in a is compared
-+   * @returns the index at which the key was found, or -n-1 if it was not
-+   *   found, where n is the index of the first value higher than key or
-+   *   a.length if there is no such value.
-+   * @exception ClassCastException if key could not be compared with one of the
-+   *   elements of a
-+   * @exception NullPointerException if a null element has compareTo called
-    */
--  public static int binarySearch(Object[] a, Object key)
-+  public static int binarySearch(Object[]a, Object key)
-   {
--    return binarySearch(a, key, null);
-+    return objectSearch(a, key, defaultComparator);
-   }
- 
-   /**
-@@ -339,310 +400,343 @@
-    *
-    * @param a the array to search (must be sorted)
-    * @param key the value to search for
--   * @param c the comparator by which the array is sorted; or null to
--   *        use the elements' natural order
--   * @return the index at which the key was found, or -n-1 if it was not
--   *         found, where n is the index of the first value higher than key or
--   *         a.length if there is no such value.
--   * @throws ClassCastException if key could not be compared with one of the
--   *         elements of a
--   * @throws NullPointerException if a null element is compared with natural
--   *         ordering (only possible when c is null)
-+   * @param c the comparator by which the array is sorted
-+   * @returns the index at which the key was found, or -n-1 if it was not
-+   *   found, where n is the index of the first value higher than key or
-+   *   a.length if there is no such value.
-+   * @exception ClassCastException if key could not be compared with one of the
-+   *   elements of a
-    */
--  public static int binarySearch(Object[] a, Object key, Comparator c)
-+  public static int binarySearch(Object[]a, Object key, Comparator c)
-   {
--    int low = 0;
--    int hi = a.length - 1;
--    int mid = 0;
--    while (low <= hi)
--      {
--        mid = (low + hi) >> 1;
--        final int d = Collections.compare(key, a[mid], c);
--        if (d == 0)
--          return mid;
--        else if (d < 0)
--          hi = mid - 1;
--        else
--          // This gets the insertion point right on the last loop
--          low = ++mid;
--      }
--    return -mid - 1;
-+    return objectSearch(a, key, c);
    }
  
 -
--// equals
-   /**
--   * Compare two boolean arrays for equality.
-+   * Compare two byte arrays for equality.
-    *
-    * @param a1 the first array to compare
-    * @param a2 the second array to compare
--   * @return true if a1 and a2 are both null, or if a2 is of the same length
--   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
-+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-    */
--  public static boolean equals(boolean[] a1, boolean[] a2)
-+  public static boolean equals(byte[]a1, byte[]a2)
-   {
-     // Quick test which saves comparing elements of the same array, and also
-     // catches the case that both are null.
-     if (a1 == a2)
--      return true;
--
-+      {
-+	return true;
-+      }
-+      
-     try
-       {
--        // If they're the same length, test each element
--        if (a1.length == a2.length)
--          {
--            int i = a1.length;
--            while (--i >= 0)
--              if (a1[i] != a2[i])
--                return false;
--            return true;
--          }
-+	// If they're the same length, test each element
-+	if (a1.length == a2.length)
-+	  {
-+	    for (int i = 0; i < a1.length; i++)
-+	      {
-+		if (a1[i] != a2[i])
-+		  {
-+		    return false;
-+		  }
-+	      }
-+	    return true;
-+	  }
-+
-+	// If a1 == null or a2 == null but not both then we will get a NullPointer
-       }
-     catch (NullPointerException e)
-       {
--        // If one is null, we get a harmless NullPointerException
-       }
- 
-     return false;
-   }
- 
-   /**
--   * Compare two byte arrays for equality.
-+   * Compare two char arrays for equality.
-    *
-    * @param a1 the first array to compare
-    * @param a2 the second array to compare
--   * @return true if a1 and a2 are both null, or if a2 is of the same length
--   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
-+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-    */
--  public static boolean equals(byte[] a1, byte[] a2)
-+  public static boolean equals(char[]a1, char[]a2)
-   {
-     // Quick test which saves comparing elements of the same array, and also
-     // catches the case that both are null.
-     if (a1 == a2)
--      return true;
--
-+      {
-+	return true;
-+      }
-+      
-     try
-       {
--        // If they're the same length, test each element
--        if (a1.length == a2.length)
--          {
--            int i = a1.length;
--            while (--i >= 0)
--              if (a1[i] != a2[i])
--                return false;
--            return true;
--          }
-+	// If they're the same length, test each element
-+	if (a1.length == a2.length)
-+	  {
-+	    for (int i = 0; i < a1.length; i++)
-+	      {
-+		if (a1[i] != a2[i])
-+		  {
-+		    return false;
-+		  }
-+	      }
-+	    return true;
-+	  }
-+
-+	// If a1 == null or a2 == null but not both then we will get a NullPointer
-       }
-     catch (NullPointerException e)
-       {
--        // If one is null, we get a harmless NullPointerException
-       }
-+
-     return false;
-   }
- 
-   /**
--   * Compare two char arrays for equality.
-+   * Compare two double arrays for equality.
-    *
-    * @param a1 the first array to compare
-    * @param a2 the second array to compare
--   * @return true if a1 and a2 are both null, or if a2 is of the same length
--   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
-+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-    */
--  public static boolean equals(char[] a1, char[] a2)
-+  public static boolean equals(double[]a1, double[]a2)
-   {
-     // Quick test which saves comparing elements of the same array, and also
-     // catches the case that both are null.
-     if (a1 == a2)
--      return true;
--
-+      {
-+	return true;
-+      }
-+      
-     try
-       {
--        // If they're the same length, test each element
--        if (a1.length == a2.length)
--          {
--            int i = a1.length;
--            while (--i >= 0)
--              if (a1[i] != a2[i])
--                return false;
--            return true;
--          }
-+	// If they're the same length, test each element
-+	if (a1.length == a2.length)
-+	  {
-+	    for (int i = 0; i < a1.length; i++)
-+	      {
-+		if (a1[i] != a2[i])
-+		  {
-+		    return false;
-+		  }
-+	      }
-+	    return true;
-+	  }
-+
-+	// If a1 == null or a2 == null but not both then we will get a NullPointer
-       }
-     catch (NullPointerException e)
-       {
--        // If one is null, we get a harmless NullPointerException
-       }
-+
-     return false;
-   }
- 
-   /**
--   * Compare two short arrays for equality.
-+   * Compare two float arrays for equality.
-    *
-    * @param a1 the first array to compare
-    * @param a2 the second array to compare
--   * @return true if a1 and a2 are both null, or if a2 is of the same length
--   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
-+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-    */
--  public static boolean equals(short[] a1, short[] a2)
-+  public static boolean equals(float[]a1, float[]a2)
-   {
-     // Quick test which saves comparing elements of the same array, and also
-     // catches the case that both are null.
-     if (a1 == a2)
--      return true;
--
-+      {
-+	return true;
-+      }
-+      
-     try
-       {
--        // If they're the same length, test each element
--        if (a1.length == a2.length)
--          {
--            int i = a1.length;
--            while (--i >= 0)
--              if (a1[i] != a2[i])
--                return false;
--            return true;
--          }
-+	// If they're the same length, test each element
-+	if (a1.length == a2.length)
-+	  {
-+	    for (int i = 0; i < a1.length; i++)
-+	      {
-+		if (a1[i] != a2[i])
-+		  {
-+		    return false;
-+		  }
-+	      }
-+	    return true;
-+	  }
-+
-+	// If a1 == null or a2 == null but not both then we will get a NullPointer
-       }
-     catch (NullPointerException e)
-       {
--        // If one is null, we get a harmless NullPointerException
-       }
-+
-     return false;
-   }
- 
-   /**
--   * Compare two int arrays for equality.
-+   * Compare two long arrays for equality.
-    *
-    * @param a1 the first array to compare
-    * @param a2 the second array to compare
--   * @return true if a1 and a2 are both null, or if a2 is of the same length
--   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
-+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-    */
--  public static boolean equals(int[] a1, int[] a2)
-+  public static boolean equals(long[]a1, long[]a2)
-   {
-     // Quick test which saves comparing elements of the same array, and also
-     // catches the case that both are null.
-     if (a1 == a2)
--      return true;
--
-+      {
-+	return true;
-+      }
-+      
-     try
-       {
--        // If they're the same length, test each element
--        if (a1.length == a2.length)
--          {
--            int i = a1.length;
--            while (--i >= 0)
--              if (a1[i] != a2[i])
--                return false;
--            return true;
--          }
-+	// If they're the same length, test each element
-+	if (a1.length == a2.length)
-+	  {
-+	    for (int i = 0; i < a1.length; i++)
-+	      {
-+		if (a1[i] != a2[i])
-+		  {
-+		    return false;
-+		  }
-+	      }
-+	    return true;
-+	  }
-+
-+	// If a1 == null or a2 == null but not both then we will get a NullPointer
-       }
-     catch (NullPointerException e)
-       {
--        // If one is null, we get a harmless NullPointerException
-       }
-+
-     return false;
-   }
- 
-   /**
--   * Compare two long arrays for equality.
-+   * Compare two short arrays for equality.
-    *
-    * @param a1 the first array to compare
-    * @param a2 the second array to compare
--   * @return true if a1 and a2 are both null, or if a2 is of the same length
--   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
-+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-    */
--  public static boolean equals(long[] a1, long[] a2)
-+  public static boolean equals(short[]a1, short[]a2)
-   {
-     // Quick test which saves comparing elements of the same array, and also
-     // catches the case that both are null.
-     if (a1 == a2)
--      return true;
--
-+      {
-+	return true;
-+      }
-+      
-     try
-       {
--        // If they're the same length, test each element
--        if (a1.length == a2.length)
--          {
--            int i = a1.length;
--            while (--i >= 0)
--              if (a1[i] != a2[i])
--                return false;
--            return true;
--          }
-+	// If they're the same length, test each element
-+	if (a1.length == a2.length)
-+	  {
-+	    for (int i = 0; i < a1.length; i++)
-+	      {
-+		if (a1[i] != a2[i])
-+		  {
-+		    return false;
-+		  }
-+	      }
-+	    return true;
-+	  }
-+
-+	// If a1 == null or a2 == null but not both then we will get a NullPointer
-       }
-     catch (NullPointerException e)
-       {
--        // If one is null, we get a harmless NullPointerException
-       }
-+
-     return false;
-   }
- 
-   /**
--   * Compare two float arrays for equality.
-+   * Compare two boolean arrays for equality.
-    *
-    * @param a1 the first array to compare
-    * @param a2 the second array to compare
--   * @return true if a1 and a2 are both null, or if a2 is of the same length
--   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
-+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-    */
--  public static boolean equals(float[] a1, float[] a2)
-+  public static boolean equals(boolean[]a1, boolean[]a2)
-   {
-     // Quick test which saves comparing elements of the same array, and also
-     // catches the case that both are null.
-     if (a1 == a2)
--      return true;
--
--    // Must use Float.compare to take into account NaN, +-0.
-+      {
-+	return true;
-+      }
-+      
-     try
-       {
--        // If they're the same length, test each element
--        if (a1.length == a2.length)
--          {
--            int i = a1.length;
--            while (--i >= 0)
--              if (Float.compare(a1[i], a2[i]) != 0)
--                return false;
--            return true;
--          }
-+	// If they're the same length, test each element
-+	if (a1.length == a2.length)
-+	  {
-+	    for (int i = 0; i < a1.length; i++)
-+	      {
-+		if (a1[i] != a2[i])
-+		  {
-+		    return false;
-+		  }
-+	      }
-+	    return true;
-+	  }
-+
-+	// If a1 == null or a2 == null but not both then we will get a NullPointer
-       }
-     catch (NullPointerException e)
-       {
--        // If one is null, we get a harmless NullPointerException
-       }
-+
-     return false;
-   }
- 
-   /**
--   * Compare two double arrays for equality.
-+   * Compare two int arrays for equality.
-    *
-    * @param a1 the first array to compare
-    * @param a2 the second array to compare
--   * @return true if a1 and a2 are both null, or if a2 is of the same length
--   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
-+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
-    */
--  public static boolean equals(double[] a1, double[] a2)
-+  public static boolean equals(int[]a1, int[]a2)
-   {
-     // Quick test which saves comparing elements of the same array, and also
-     // catches the case that both are null.
-     if (a1 == a2)
--      return true;
--
--    // Must use Double.compare to take into account NaN, +-0.
-+      {
-+	return true;
-+      }
-+      
-     try
-       {
--        // If they're the same length, test each element
--        if (a1.length == a2.length)
--          {
--            int i = a1.length;
--            while (--i >= 0)
--              if (Double.compare(a1[i], a2[i]) != 0)
--                return false;
--            return true;
--          }
-+	// If they're the same length, test each element
-+	if (a1.length == a2.length)
-+	  {
-+	    for (int i = 0; i < a1.length; i++)
-+	      {
-+		if (a1[i] != a2[i])
-+		  {
-+		    return false;
-+		  }
-+	      }
-+	    return true;
-+	  }
-+
-+	// If a1 == null or a2 == null but not both then we will get a NullPointer
-       }
-     catch (NullPointerException e)
-       {
--        // If one is null, we get a harmless NullPointerException
-       }
-+
-     return false;
-   }
- 
-@@ -651,46 +745,54 @@
-    *
-    * @param a1 the first array to compare
-    * @param a2 the second array to compare
--   * @return true if a1 and a2 are both null, or if a1 is of the same length
--   *         as a2, and for each 0 <= i < a.length, a1[i] == null ?
--   *         a2[i] == null : a1[i].equals(a2[i]).
-+   * @returns true if a1 and a2 are both null, or if a1 is of the same length
-+   *   as a2, and for each 0 <= i < a.length, a1[i] == null ? a2[i] == null :
-+   *   a1[i].equals(a2[i]).
-    */
--  public static boolean equals(Object[] a1, Object[] a2)
-+  public static boolean equals(Object[]a1, Object[]a2)
-   {
-     // Quick test which saves comparing elements of the same array, and also
-     // catches the case that both are null.
-     if (a1 == a2)
--      return true;
--
-+      {
-+	return true;
-+      }
-+      
-     try
-       {
--        // If they're the same length, test each element
--        if (a1.length == a2.length)
--          {
--            int i = a1.length;
--            while (--i >= 0)
--              if (! AbstractCollection.equals(a1[i], a2[i]))
--                return false;
--            return true;
--          }
-+	// If they're the same length, test each element
-+	if (a1.length == a2.length)
-+	  {
-+	    for (int i = 0; i < a1.length; i++)
-+	      {
-+		if (!(a1[i] == null ? a2[i] == null : a1[i].equals(a2[i])))
-+		  {
-+		    return false;
-+		  }
-+	      }
-+	    return true;
-+	  }
-+
-+	// If a1 == null or a2 == null but not both then we will get a NullPointer
-       }
-     catch (NullPointerException e)
-       {
--        // If one is null, we get a harmless NullPointerException
-       }
-+
-     return false;
-   }
- 
--
--// fill
-   /**
-    * Fill an array with a boolean value.
-    *
-    * @param a the array to fill
-    * @param val the value to fill it with
-    */
--  public static void fill(boolean[] a, boolean val)
-+  public static void fill(boolean[]a, boolean val)
-   {
-+    // This implementation is slightly inefficient timewise, but the extra
-+    // effort over inlining it is O(1) and small, and I refuse to repeat code
-+    // if it can be helped.
-     fill(a, 0, a.length, val);
-   }
- 
-@@ -701,16 +803,13 @@
-    * @param fromIndex the index to fill from, inclusive
-    * @param toIndex the index to fill to, exclusive
-    * @param val the value to fill with
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
-    */
--  public static void fill(boolean[] a, int fromIndex, int toIndex, boolean val)
-+  public static void fill(boolean[]a, int fromIndex, int toIndex, boolean val)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
-     for (int i = fromIndex; i < toIndex; i++)
--      a[i] = val;
-+      {
-+	a[i] = val;
-+      }
-   }
- 
-   /**
-@@ -719,8 +818,11 @@
-    * @param a the array to fill
-    * @param val the value to fill it with
-    */
--  public static void fill(byte[] a, byte val)
-+  public static void fill(byte[]a, byte val)
-   {
-+    // This implementation is slightly inefficient timewise, but the extra
-+    // effort over inlining it is O(1) and small, and I refuse to repeat code
-+    // if it can be helped.
-     fill(a, 0, a.length, val);
-   }
- 
-@@ -731,16 +833,13 @@
-    * @param fromIndex the index to fill from, inclusive
-    * @param toIndex the index to fill to, exclusive
-    * @param val the value to fill with
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
-    */
--  public static void fill(byte[] a, int fromIndex, int toIndex, byte val)
-+  public static void fill(byte[]a, int fromIndex, int toIndex, byte val)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
-     for (int i = fromIndex; i < toIndex; i++)
--      a[i] = val;
-+      {
-+	a[i] = val;
-+      }
-   }
- 
-   /**
-@@ -749,8 +848,11 @@
-    * @param a the array to fill
-    * @param val the value to fill it with
-    */
--  public static void fill(char[] a, char val)
-+  public static void fill(char[]a, char val)
-   {
-+    // This implementation is slightly inefficient timewise, but the extra
-+    // effort over inlining it is O(1) and small, and I refuse to repeat code
-+    // if it can be helped.
-     fill(a, 0, a.length, val);
-   }
- 
-@@ -761,166 +863,163 @@
-    * @param fromIndex the index to fill from, inclusive
-    * @param toIndex the index to fill to, exclusive
-    * @param val the value to fill with
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
-    */
--  public static void fill(char[] a, int fromIndex, int toIndex, char val)
-+  public static void fill(char[]a, int fromIndex, int toIndex, char val)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
-     for (int i = fromIndex; i < toIndex; i++)
--      a[i] = val;
-+      {
-+	a[i] = val;
-+      }
-   }
- 
-   /**
--   * Fill an array with a short value.
-+   * Fill an array with a double value.
-    *
-    * @param a the array to fill
-    * @param val the value to fill it with
-    */
--  public static void fill(short[] a, short val)
-+  public static void fill(double[]a, double val)
-   {
-+    // This implementation is slightly inefficient timewise, but the extra
-+    // effort over inlining it is O(1) and small, and I refuse to repeat code
-+    // if it can be helped.
-     fill(a, 0, a.length, val);
-   }
- 
-   /**
--   * Fill a range of an array with a short value.
-+   * Fill a range of an array with a double value.
-    *
-    * @param a the array to fill
-    * @param fromIndex the index to fill from, inclusive
-    * @param toIndex the index to fill to, exclusive
-    * @param val the value to fill with
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
-    */
--  public static void fill(short[] a, int fromIndex, int toIndex, short val)
-+  public static void fill(double[]a, int fromIndex, int toIndex, double val)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
-     for (int i = fromIndex; i < toIndex; i++)
--      a[i] = val;
-+      {
-+	a[i] = val;
-+      }
-   }
- 
-   /**
--   * Fill an array with an int value.
-+   * Fill an array with a float value.
-    *
-    * @param a the array to fill
-    * @param val the value to fill it with
-    */
--  public static void fill(int[] a, int val)
-+  public static void fill(float[]a, float val)
-   {
-+    // This implementation is slightly inefficient timewise, but the extra
-+    // effort over inlining it is O(1) and small, and I refuse to repeat code
-+    // if it can be helped.
-     fill(a, 0, a.length, val);
-   }
- 
-   /**
--   * Fill a range of an array with an int value.
-+   * Fill a range of an array with a float value.
-    *
-    * @param a the array to fill
-    * @param fromIndex the index to fill from, inclusive
-    * @param toIndex the index to fill to, exclusive
-    * @param val the value to fill with
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
-    */
--  public static void fill(int[] a, int fromIndex, int toIndex, int val)
-+  public static void fill(float[]a, int fromIndex, int toIndex, float val)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
-     for (int i = fromIndex; i < toIndex; i++)
--      a[i] = val;
-+      {
-+	a[i] = val;
-+      }
-   }
- 
-   /**
--   * Fill an array with a long value.
-+   * Fill an array with an int value.
-    *
-    * @param a the array to fill
-    * @param val the value to fill it with
-    */
--  public static void fill(long[] a, long val)
-+  public static void fill(int[]a, int val)
-   {
-+    // This implementation is slightly inefficient timewise, but the extra
-+    // effort over inlining it is O(1) and small, and I refuse to repeat code
-+    // if it can be helped.
-     fill(a, 0, a.length, val);
-   }
- 
-   /**
--   * Fill a range of an array with a long value.
-+   * Fill a range of an array with an int value.
-    *
-    * @param a the array to fill
-    * @param fromIndex the index to fill from, inclusive
-    * @param toIndex the index to fill to, exclusive
-    * @param val the value to fill with
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
-    */
--  public static void fill(long[] a, int fromIndex, int toIndex, long val)
-+  public static void fill(int[]a, int fromIndex, int toIndex, int val)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
-     for (int i = fromIndex; i < toIndex; i++)
--      a[i] = val;
-+      {
-+	a[i] = val;
-+      }
-   }
- 
-   /**
--   * Fill an array with a float value.
-+   * Fill an array with a long value.
-    *
-    * @param a the array to fill
-    * @param val the value to fill it with
-    */
--  public static void fill(float[] a, float val)
-+  public static void fill(long[]a, long val)
-   {
-+    // This implementation is slightly inefficient timewise, but the extra
-+    // effort over inlining it is O(1) and small, and I refuse to repeat code
-+    // if it can be helped.
-     fill(a, 0, a.length, val);
-   }
- 
-   /**
--   * Fill a range of an array with a float value.
-+   * Fill a range of an array with a long value.
-    *
-    * @param a the array to fill
-    * @param fromIndex the index to fill from, inclusive
-    * @param toIndex the index to fill to, exclusive
-    * @param val the value to fill with
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
-    */
--  public static void fill(float[] a, int fromIndex, int toIndex, float val)
-+  public static void fill(long[]a, int fromIndex, int toIndex, long val)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
-     for (int i = fromIndex; i < toIndex; i++)
--      a[i] = val;
-+      {
-+	a[i] = val;
-+      }
-   }
- 
-   /**
--   * Fill an array with a double value.
-+   * Fill an array with a short value.
-    *
-    * @param a the array to fill
-    * @param val the value to fill it with
-    */
--  public static void fill(double[] a, double val)
-+  public static void fill(short[]a, short val)
-   {
-+    // This implementation is slightly inefficient timewise, but the extra
-+    // effort over inlining it is O(1) and small, and I refuse to repeat code
-+    // if it can be helped.
-     fill(a, 0, a.length, val);
-   }
- 
-   /**
--   * Fill a range of an array with a double value.
-+   * Fill a range of an array with a short value.
-    *
-    * @param a the array to fill
-    * @param fromIndex the index to fill from, inclusive
-    * @param toIndex the index to fill to, exclusive
-    * @param val the value to fill with
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
-    */
--  public static void fill(double[] a, int fromIndex, int toIndex, double val)
-+  public static void fill(short[]a, int fromIndex, int toIndex, short val)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
-     for (int i = fromIndex; i < toIndex; i++)
--      a[i] = val;
-+      {
-+	a[i] = val;
-+      }
-   }
- 
-   /**
-@@ -928,11 +1027,14 @@
-    *
-    * @param a the array to fill
-    * @param val the value to fill it with
--   * @throws ClassCastException if val is not an instance of the element
--   *         type of a.
-+   * @exception ClassCastException if val is not an instance of the element
-+   *   type of a.
-    */
--  public static void fill(Object[] a, Object val)
-+  public static void fill(Object[]a, Object val)
-   {
-+    // This implementation is slightly inefficient timewise, but the extra
-+    // effort over inlining it is O(1) and small, and I refuse to repeat code
-+    // if it can be helped.
-     fill(a, 0, a.length, val);
-   }
- 
-@@ -943,1191 +1045,926 @@
-    * @param fromIndex the index to fill from, inclusive
-    * @param toIndex the index to fill to, exclusive
-    * @param val the value to fill with
--   * @throws ClassCastException if val is not an instance of the element
--   *         type of a.
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
-+   * @exception ClassCastException if val is not an instance of the element
-+   *   type of a.
-    */
--  public static void fill(Object[] a, int fromIndex, int toIndex, Object val)
-+  public static void fill(Object[]a, int fromIndex, int toIndex, Object val)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
-     for (int i = fromIndex; i < toIndex; i++)
--      a[i] = val;
-+      {
-+	a[i] = val;
-+      }
-   }
- 
--
--// sort
-   // Thanks to Paul Fisher <rao@gnu.org> for finding this quicksort algorithm
--  // as specified by Sun and porting it to Java. The algorithm is an optimised
--  // quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's
--  // "Engineering a Sort Function", Software-Practice and Experience, Vol.
--  // 23(11) P. 1249-1265 (November 1993). This algorithm gives n*log(n)
--  // performance on many arrays that would take quadratic time with a standard
--  // quicksort.
-+  // as specified by Sun and porting it to Java.
- 
-   /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
-+   * Sort a byte array into ascending order. The sort algorithm is an optimised
-+   * quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's
-+   * "Engineering a Sort Function", Software-Practice and Experience, Vol.
-+   * 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
-+   * performance on many arrays that would take quadratic time with a standard
-+   * quicksort.
-    *
--   * @param a the byte array to sort
-+   * @param a the array to sort
-    */
--  public static void sort(byte[] a)
-+  public static void sort(byte[]a)
-   {
-     qsort(a, 0, a.length);
-   }
- 
--  /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
--   *
--   * @param a the byte array to sort
--   * @param fromIndex the first index to sort (inclusive)
--   * @param toIndex the last index to sort (exclusive)
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
--   */
-   public static void sort(byte[] a, int fromIndex, int toIndex)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
--    qsort(a, fromIndex, toIndex - fromIndex);
-+    qsort(a, fromIndex, toIndex);
-   }
- 
--  /**
--   * Finds the index of the median of three array elements.
--   *
--   * @param a the first index
--   * @param b the second index
--   * @param c the third index
--   * @param d the array
--   * @return the index (a, b, or c) which has the middle value of the three
--   */
--  private static int med3(int a, int b, int c, byte[] d)
-+  private static int med3(int a, int b, int c, byte[]d)
-   {
--    return (d[a] < d[b]
--            ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
--            : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
-+    return d[a] < d[b] ? 
-+               (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
-+	     : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);
-   }
- 
--  /**
--   * Swaps the elements at two locations of an array
--   *
--   * @param i the first index
--   * @param j the second index
--   * @param a the array
--   */
--  private static void swap(int i, int j, byte[] a)
-+  private static void swap(int i, int j, byte[]a)
-   {
-     byte c = a[i];
-     a[i] = a[j];
-     a[j] = c;
-   }
- 
--  /**
--   * Swaps two ranges of an array.
--   *
--   * @param i the first range start
--   * @param j the second range start
--   * @param n the element count
--   * @param a the array
--   */
--  private static void vecswap(int i, int j, int n, byte[] a)
-+  private static void qsort(byte[]a, int start, int n)
-   {
--    for ( ; n > 0; i++, j++, n--)
--      swap(i, j, a);
-+    // use an insertion sort on small arrays
-+    if (n <= 7)
-+      {
-+	for (int i = start + 1; i < start + n; i++)
-+	  for (int j = i; j > 0 && a[j - 1] > a[j]; j--)
-+	    swap(j, j - 1, a);
-+	return;
-+      }
-+
-+    int pm = n / 2;		// small arrays, middle element
-+    if (n > 7)
-+      {
-+	int pl = start;
-+	int pn = start + n - 1;
-+
-+	if (n > 40)
-+	  {			// big arrays, pseudomedian of 9
-+	    int s = n / 8;
-+	    pl = med3(pl, pl + s, pl + 2 * s, a);
-+	    pm = med3(pm - s, pm, pm + s, a);
-+	    pn = med3(pn - 2 * s, pn - s, pn, a);
-+	  }
-+	pm = med3(pl, pm, pn, a);	// mid-size, med of 3
-+      }
-+
-+    int pa, pb, pc, pd, pv;
-+    int r;
-+
-+    pv = start;
-+    swap(pv, pm, a);
-+    pa = pb = start;
-+    pc = pd = start + n - 1;
-+
-+    for (;;)
-+      {
-+	while (pb <= pc && (r = a[pb] - a[pv]) <= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pa, pb, a);
-+		pa++;
-+	      }
-+	    pb++;
-+	  }
-+	while (pc >= pb && (r = a[pc] - a[pv]) >= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pc, pd, a);
-+		pd--;
-+	      }
-+	    pc--;
-+	  }
-+	if (pb > pc)
-+	  break;
-+	swap(pb, pc, a);
-+	pb++;
-+	pc--;
-+      }
-+    int pn = start + n;
-+    int s;
-+    s = Math.min(pa - start, pb - pa);
-+    vecswap(start, pb - s, s, a);
-+    s = Math.min(pd - pc, pn - pd - 1);
-+    vecswap(pb, pn - s, s, a);
-+    if ((s = pb - pa) > 1)
-+      qsort(a, start, s);
-+    if ((s = pd - pc) > 1)
-+      qsort(a, pn - s, s);
-   }
- 
--  /**
--   * Performs a recursive modified quicksort.
--   *
--   * @param a the array to sort
--   * @param from the start index (inclusive)
--   * @param count the number of elements to sort
--   */
--  private static void qsort(byte[] array, int from, int count)
-+  private static void vecswap(int i, int j, int n, byte[]a)
-   {
--    // Use an insertion sort on small arrays.
--    if (count <= 7)
--      {
--        for (int i = from + 1; i < from + count; i++)
--          for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
--            swap(j, j - 1, array);
--        return;
--      }
--
--    // Determine a good median element.
--    int mid = count / 2;
--    int lo = from;
--    int hi = from + count - 1;
--
--    if (count > 40)
--      { // big arrays, pseudomedian of 9
--        int s = count / 8;
--        lo = med3(lo, lo + s, lo + s + s, array);
--        mid = med3(mid - s, mid, mid + s, array);
--        hi = med3(hi - s - s, hi - s, hi, array);
--      }
--    mid = med3(lo, mid, hi, array);
--
--    int a, b, c, d;
--    int comp;
--
--    // Pull the median element out of the fray, and use it as a pivot.
--    swap(from, mid, array);
--    a = b = from + 1;
--    c = d = hi;
--
--    // Repeatedly move b and c to each other, swapping elements so
--    // that all elements before index b are less than the pivot, and all
--    // elements after index c are greater than the pivot. a and b track
--    // the elements equal to the pivot.
--    while (true)
--      {
--        while (b <= c && (comp = array[b] - array[from]) <= 0)
--          {
--            if (comp == 0)
--              {
--                swap(a, b, array);
--                a++;
--              }
--            b++;
--          }
--        while (c >= b && (comp = array[c] - array[from]) >= 0)
--          {
--            if (comp == 0)
--              {
--                swap(c, d, array);
--                d--;
--              }
--            c--;
--          }
--        if (b > c)
--          break;
--        swap(b, c, array);
--        b++;
--        c--;
--      }
--
--    // Swap pivot(s) back in place, the recurse on left and right sections.
--    int span;
--    span = Math.min(a - from, b - a);
--    vecswap(from, b - span, span, array);
--
--    span = Math.min(d - c, hi - d - 1);
--    vecswap(b, hi - span + 1, span, array);
--
--    span = b - a;
--    if (span > 1)
--      qsort(array, from, span);
--
--    span = d - c;
--    if (span > 1)
--      qsort(array, hi - span + 1, span);
-+    for (; n > 0; i++, j++, n--)
-+      swap(i, j, a);
-   }
- 
-   /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
-+   * Sort a char array into ascending order. The sort algorithm is an optimised
-+   * quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's
-+   * "Engineering a Sort Function", Software-Practice and Experience, Vol.
-+   * 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
-+   * performance on many arrays that would take quadratic time with a standard
-+   * quicksort.
-    *
--   * @param a the char array to sort
-+   * @param a the array to sort
-    */
--  public static void sort(char[] a)
-+  public static void sort(char[]a)
-   {
-     qsort(a, 0, a.length);
-   }
- 
--  /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
--   *
--   * @param a the char array to sort
--   * @param fromIndex the first index to sort (inclusive)
--   * @param toIndex the last index to sort (exclusive)
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
--   */
-   public static void sort(char[] a, int fromIndex, int toIndex)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
--    qsort(a, fromIndex, toIndex - fromIndex);
-+    qsort(a, fromIndex, toIndex);
-   }
- 
--  /**
--   * Finds the index of the median of three array elements.
--   *
--   * @param a the first index
--   * @param b the second index
--   * @param c the third index
--   * @param d the array
--   * @return the index (a, b, or c) which has the middle value of the three
--   */
--  private static int med3(int a, int b, int c, char[] d)
-+  private static int med3(int a, int b, int c, char[]d)
-   {
--    return (d[a] < d[b]
--            ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
--            : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
-+    return d[a] < d[b] ? 
-+               (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
-+	     : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);
-   }
- 
--  /**
--   * Swaps the elements at two locations of an array
--   *
--   * @param i the first index
--   * @param j the second index
--   * @param a the array
--   */
--  private static void swap(int i, int j, char[] a)
-+  private static void swap(int i, int j, char[]a)
-   {
-     char c = a[i];
-     a[i] = a[j];
-     a[j] = c;
-   }
- 
--  /**
--   * Swaps two ranges of an array.
--   *
--   * @param i the first range start
--   * @param j the second range start
--   * @param n the element count
--   * @param a the array
--   */
--  private static void vecswap(int i, int j, int n, char[] a)
-+  private static void qsort(char[]a, int start, int n)
-   {
--    for ( ; n > 0; i++, j++, n--)
--      swap(i, j, a);
-+    // use an insertion sort on small arrays
-+    if (n <= 7)
-+      {
-+	for (int i = start + 1; i < start + n; i++)
-+	  for (int j = i; j > 0 && a[j - 1] > a[j]; j--)
-+	    swap(j, j - 1, a);
-+	return;
-+      }
-+
-+    int pm = n / 2;		// small arrays, middle element
-+    if (n > 7)
-+      {
-+	int pl = start;
-+	int pn = start + n - 1;
-+
-+	if (n > 40)
-+	  {			// big arrays, pseudomedian of 9
-+	    int s = n / 8;
-+	    pl = med3(pl, pl + s, pl + 2 * s, a);
-+	    pm = med3(pm - s, pm, pm + s, a);
-+	    pn = med3(pn - 2 * s, pn - s, pn, a);
-+	  }
-+	pm = med3(pl, pm, pn, a);	// mid-size, med of 3
-+      }
-+
-+    int pa, pb, pc, pd, pv;
-+    int r;
-+
-+    pv = start;
-+    swap(pv, pm, a);
-+    pa = pb = start;
-+    pc = pd = start + n - 1;
-+
-+    for (;;)
-+      {
-+	while (pb <= pc && (r = a[pb] - a[pv]) <= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pa, pb, a);
-+		pa++;
-+	      }
-+	    pb++;
-+	  }
-+	while (pc >= pb && (r = a[pc] - a[pv]) >= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pc, pd, a);
-+		pd--;
-+	      }
-+	    pc--;
-+	  }
-+	if (pb > pc)
-+	  break;
-+	swap(pb, pc, a);
-+	pb++;
-+	pc--;
-+      }
-+    int pn = start + n;
-+    int s;
-+    s = Math.min(pa - start, pb - pa);
-+    vecswap(start, pb - s, s, a);
-+    s = Math.min(pd - pc, pn - pd - 1);
-+    vecswap(pb, pn - s, s, a);
-+    if ((s = pb - pa) > 1)
-+      qsort(a, start, s);
-+    if ((s = pd - pc) > 1)
-+      qsort(a, pn - s, s);
-   }
- 
--  /**
--   * Performs a recursive modified quicksort.
--   *
--   * @param a the array to sort
--   * @param from the start index (inclusive)
--   * @param count the number of elements to sort
--   */
--  private static void qsort(char[] array, int from, int count)
-+  private static void vecswap(int i, int j, int n, char[]a)
-   {
--    // Use an insertion sort on small arrays.
--    if (count <= 7)
--      {
--        for (int i = from + 1; i < from + count; i++)
--          for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
--            swap(j, j - 1, array);
--        return;
--      }
--
--    // Determine a good median element.
--    int mid = count / 2;
--    int lo = from;
--    int hi = from + count - 1;
--
--    if (count > 40)
--      { // big arrays, pseudomedian of 9
--        int s = count / 8;
--        lo = med3(lo, lo + s, lo + s + s, array);
--        mid = med3(mid - s, mid, mid + s, array);
--        hi = med3(hi - s - s, hi - s, hi, array);
--      }
--    mid = med3(lo, mid, hi, array);
--
--    int a, b, c, d;
--    int comp;
--
--    // Pull the median element out of the fray, and use it as a pivot.
--    swap(from, mid, array);
--    a = b = from + 1;
--    c = d = hi;
--
--    // Repeatedly move b and c to each other, swapping elements so
--    // that all elements before index b are less than the pivot, and all
--    // elements after index c are greater than the pivot. a and b track
--    // the elements equal to the pivot.
--    while (true)
--      {
--        while (b <= c && (comp = array[b] - array[from]) <= 0)
--          {
--            if (comp == 0)
--              {
--                swap(a, b, array);
--                a++;
--              }
--            b++;
--          }
--        while (c >= b && (comp = array[c] - array[from]) >= 0)
--          {
--            if (comp == 0)
--              {
--                swap(c, d, array);
--                d--;
--              }
--            c--;
--          }
--        if (b > c)
--          break;
--        swap(b, c, array);
--        b++;
--        c--;
--      }
--
--    // Swap pivot(s) back in place, the recurse on left and right sections.
--    int span;
--    span = Math.min(a - from, b - a);
--    vecswap(from, b - span, span, array);
--
--    span = Math.min(d - c, hi - d - 1);
--    vecswap(b, hi - span + 1, span, array);
--
--    span = b - a;
--    if (span > 1)
--      qsort(array, from, span);
--
--    span = d - c;
--    if (span > 1)
--      qsort(array, hi - span + 1, span);
-+    for (; n > 0; i++, j++, n--)
-+      swap(i, j, a);
-   }
- 
-   /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
-+   * Sort a double array into ascending order. The sort algorithm is an
-+   * optimised quicksort, as described in Jon L. Bentley and M. Douglas
-+   * McIlroy's "Engineering a Sort Function", Software-Practice and Experience,
-+   * Vol. 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
-+   * performance on many arrays that would take quadratic time with a standard
-+   * quicksort. Note that this implementation, like Sun's, has undefined
-+   * behaviour if the array contains any NaN values.
-    *
--   * @param a the short array to sort
-+   * @param a the array to sort
-    */
--  public static void sort(short[] a)
-+  public static void sort(double[]a)
-   {
-     qsort(a, 0, a.length);
-   }
- 
--  /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
--   *
--   * @param a the short array to sort
--   * @param fromIndex the first index to sort (inclusive)
--   * @param toIndex the last index to sort (exclusive)
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
--   */
--  public static void sort(short[] a, int fromIndex, int toIndex)
-+  public static void sort(double[] a, int fromIndex, int toIndex)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
--    qsort(a, fromIndex, toIndex - fromIndex);
-+    qsort(a, fromIndex, toIndex);
-   }
- 
--  /**
--   * Finds the index of the median of three array elements.
--   *
--   * @param a the first index
--   * @param b the second index
--   * @param c the third index
--   * @param d the array
--   * @return the index (a, b, or c) which has the middle value of the three
--   */
--  private static int med3(int a, int b, int c, short[] d)
-+  private static int med3(int a, int b, int c, double[]d)
-   {
--    return (d[a] < d[b]
--            ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
--            : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
-+    return d[a] < d[b] ? 
-+               (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
-+	     : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);
-   }
- 
--  /**
--   * Swaps the elements at two locations of an array
--   *
--   * @param i the first index
--   * @param j the second index
--   * @param a the array
--   */
--  private static void swap(int i, int j, short[] a)
-+  private static void swap(int i, int j, double[]a)
-   {
--    short c = a[i];
-+    double c = a[i];
-     a[i] = a[j];
-     a[j] = c;
-   }
- 
--  /**
--   * Swaps two ranges of an array.
--   *
--   * @param i the first range start
--   * @param j the second range start
--   * @param n the element count
--   * @param a the array
--   */
--  private static void vecswap(int i, int j, int n, short[] a)
-+  private static void qsort(double[]a, int start, int n)
-   {
--    for ( ; n > 0; i++, j++, n--)
--      swap(i, j, a);
-+    // use an insertion sort on small arrays
-+    if (n <= 7)
-+      {
-+	for (int i = start + 1; i < start + n; i++)
-+	  for (int j = i; j > 0 && a[j - 1] > a[j]; j--)
-+	    swap(j, j - 1, a);
-+	return;
-+      }
-+
-+    int pm = n / 2;		// small arrays, middle element
-+    if (n > 7)
-+      {
-+	int pl = start;
-+	int pn = start + n - 1;
-+
-+	if (n > 40)
-+	  {			// big arrays, pseudomedian of 9
-+	    int s = n / 8;
-+	    pl = med3(pl, pl + s, pl + 2 * s, a);
-+	    pm = med3(pm - s, pm, pm + s, a);
-+	    pn = med3(pn - 2 * s, pn - s, pn, a);
-+	  }
-+	pm = med3(pl, pm, pn, a);	// mid-size, med of 3
-+      }
-+
-+    int pa, pb, pc, pd, pv;
-+    double r;
-+
-+    pv = start;
-+    swap(pv, pm, a);
-+    pa = pb = start;
-+    pc = pd = start + n - 1;
-+
-+    for (;;)
-+      {
-+	while (pb <= pc && (r = a[pb] - a[pv]) <= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pa, pb, a);
-+		pa++;
-+	      }
-+	    pb++;
-+	  }
-+	while (pc >= pb && (r = a[pc] - a[pv]) >= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pc, pd, a);
-+		pd--;
-+	      }
-+	    pc--;
-+	  }
-+	if (pb > pc)
-+	  break;
-+	swap(pb, pc, a);
-+	pb++;
-+	pc--;
-+      }
-+    int pn = start + n;
-+    int s;
-+    s = Math.min(pa - start, pb - pa);
-+    vecswap(start, pb - s, s, a);
-+    s = Math.min(pd - pc, pn - pd - 1);
-+    vecswap(pb, pn - s, s, a);
-+    if ((s = pb - pa) > 1)
-+      qsort(a, start, s);
-+    if ((s = pd - pc) > 1)
-+      qsort(a, pn - s, s);
-   }
- 
--  /**
--   * Performs a recursive modified quicksort.
--   *
--   * @param a the array to sort
--   * @param from the start index (inclusive)
--   * @param count the number of elements to sort
--   */
--  private static void qsort(short[] array, int from, int count)
-+  private static void vecswap(int i, int j, int n, double[]a)
-   {
--    // Use an insertion sort on small arrays.
--    if (count <= 7)
--      {
--        for (int i = from + 1; i < from + count; i++)
--          for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
--            swap(j, j - 1, array);
--        return;
--      }
--
--    // Determine a good median element.
--    int mid = count / 2;
--    int lo = from;
--    int hi = from + count - 1;
--
--    if (count > 40)
--      { // big arrays, pseudomedian of 9
--        int s = count / 8;
--        lo = med3(lo, lo + s, lo + s + s, array);
--        mid = med3(mid - s, mid, mid + s, array);
--        hi = med3(hi - s - s, hi - s, hi, array);
--      }
--    mid = med3(lo, mid, hi, array);
--
--    int a, b, c, d;
--    int comp;
--
--    // Pull the median element out of the fray, and use it as a pivot.
--    swap(from, mid, array);
--    a = b = from + 1;
--    c = d = hi;
--
--    // Repeatedly move b and c to each other, swapping elements so
--    // that all elements before index b are less than the pivot, and all
--    // elements after index c are greater than the pivot. a and b track
--    // the elements equal to the pivot.
--    while (true)
--      {
--        while (b <= c && (comp = array[b] - array[from]) <= 0)
--          {
--            if (comp == 0)
--              {
--                swap(a, b, array);
--                a++;
--              }
--            b++;
--          }
--        while (c >= b && (comp = array[c] - array[from]) >= 0)
--          {
--            if (comp == 0)
--              {
--                swap(c, d, array);
--                d--;
--              }
--            c--;
--          }
--        if (b > c)
--          break;
--        swap(b, c, array);
--        b++;
--        c--;
--      }
--
--    // Swap pivot(s) back in place, the recurse on left and right sections.
--    int span;
--    span = Math.min(a - from, b - a);
--    vecswap(from, b - span, span, array);
--
--    span = Math.min(d - c, hi - d - 1);
--    vecswap(b, hi - span + 1, span, array);
--
--    span = b - a;
--    if (span > 1)
--      qsort(array, from, span);
--
--    span = d - c;
--    if (span > 1)
--      qsort(array, hi - span + 1, span);
-+    for (; n > 0; i++, j++, n--)
-+      swap(i, j, a);
-   }
- 
-   /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
-+   * Sort a float array into ascending order. The sort algorithm is an
-+   * optimised quicksort, as described in Jon L. Bentley and M. Douglas
-+   * McIlroy's "Engineering a Sort Function", Software-Practice and Experience,
-+   * Vol. 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
-+   * performance on many arrays that would take quadratic time with a standard
-+   * quicksort. Note that this implementation, like Sun's, has undefined
-+   * behaviour if the array contains any NaN values.
-    *
--   * @param a the int array to sort
-+   * @param a the array to sort
-    */
--  public static void sort(int[] a)
-+  public static void sort(float[]a)
-   {
-     qsort(a, 0, a.length);
-   }
- 
--  /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
--   *
--   * @param a the int array to sort
--   * @param fromIndex the first index to sort (inclusive)
--   * @param toIndex the last index to sort (exclusive)
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
--   */
--  public static void sort(int[] a, int fromIndex, int toIndex)
-+  public static void sort(float[] a, int fromIndex, int toIndex)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
--    qsort(a, fromIndex, toIndex - fromIndex);
-+    qsort(a, fromIndex, toIndex);
-   }
- 
--  /**
--   * Finds the index of the median of three array elements.
--   *
--   * @param a the first index
--   * @param b the second index
--   * @param c the third index
--   * @param d the array
--   * @return the index (a, b, or c) which has the middle value of the three
--   */
--  private static int med3(int a, int b, int c, int[] d)
-+  private static int med3(int a, int b, int c, float[]d)
-   {
--    return (d[a] < d[b]
--            ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
--            : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
-+    return d[a] < d[b] ? 
-+               (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
-+	     : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);
-   }
- 
--  /**
--   * Swaps the elements at two locations of an array
--   *
--   * @param i the first index
--   * @param j the second index
--   * @param a the array
--   */
--  private static void swap(int i, int j, int[] a)
-+  private static void swap(int i, int j, float[]a)
-   {
--    int c = a[i];
-+    float c = a[i];
-     a[i] = a[j];
-     a[j] = c;
-   }
- 
--  /**
--   * Swaps two ranges of an array.
--   *
--   * @param i the first range start
--   * @param j the second range start
--   * @param n the element count
--   * @param a the array
--   */
--  private static void vecswap(int i, int j, int n, int[] a)
-+  private static void qsort(float[]a, int start, int n)
-   {
--    for ( ; n > 0; i++, j++, n--)
--      swap(i, j, a);
-+    // use an insertion sort on small arrays
-+    if (n <= 7)
-+      {
-+	for (int i = start + 1; i < start + n; i++)
-+	  for (int j = i; j > 0 && a[j - 1] > a[j]; j--)
-+	    swap(j, j - 1, a);
-+	return;
-+      }
-+
-+    int pm = n / 2;		// small arrays, middle element
-+    if (n > 7)
-+      {
-+	int pl = start;
-+	int pn = start + n - 1;
-+
-+	if (n > 40)
-+	  {			// big arrays, pseudomedian of 9
-+	    int s = n / 8;
-+	    pl = med3(pl, pl + s, pl + 2 * s, a);
-+	    pm = med3(pm - s, pm, pm + s, a);
-+	    pn = med3(pn - 2 * s, pn - s, pn, a);
-+	  }
-+	pm = med3(pl, pm, pn, a);	// mid-size, med of 3
-+      }
-+
-+    int pa, pb, pc, pd, pv;
-+    float r;
-+
-+    pv = start;
-+    swap(pv, pm, a);
-+    pa = pb = start;
-+    pc = pd = start + n - 1;
-+
-+    for (;;)
-+      {
-+	while (pb <= pc && (r = a[pb] - a[pv]) <= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pa, pb, a);
-+		pa++;
-+	      }
-+	    pb++;
-+	  }
-+	while (pc >= pb && (r = a[pc] - a[pv]) >= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pc, pd, a);
-+		pd--;
-+	      }
-+	    pc--;
-+	  }
-+	if (pb > pc)
-+	  break;
-+	swap(pb, pc, a);
-+	pb++;
-+	pc--;
-+      }
-+    int pn = start + n;
-+    int s;
-+    s = Math.min(pa - start, pb - pa);
-+    vecswap(start, pb - s, s, a);
-+    s = Math.min(pd - pc, pn - pd - 1);
-+    vecswap(pb, pn - s, s, a);
-+    if ((s = pb - pa) > 1)
-+      qsort(a, start, s);
-+    if ((s = pd - pc) > 1)
-+      qsort(a, pn - s, s);
-   }
- 
--  /**
--   * Compares two integers in natural order, since a - b is inadequate.
--   *
--   * @param a the first int
--   * @param b the second int
--   * @return &lt; 0, 0, or &gt; 0 accorting to the comparison
--   */
--  private static int compare(int a, int b)
-+  private static void vecswap(int i, int j, int n, float[]a)
-   {
--    return a < b ? -1 : a == b ? 0 : 1;
-+    for (; n > 0; i++, j++, n--)
-+      swap(i, j, a);
-   }
- 
-   /**
--   * Performs a recursive modified quicksort.
-+   * Sort an int array into ascending order. The sort algorithm is an optimised
-+   * quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's
-+   * "Engineering a Sort Function", Software-Practice and Experience, Vol.
-+   * 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
-+   * performance on many arrays that would take quadratic time with a standard
-+   * quicksort.
-    *
-    * @param a the array to sort
--   * @param from the start index (inclusive)
--   * @param count the number of elements to sort
--   */
--  private static void qsort(int[] array, int from, int count)
--  {
--    // Use an insertion sort on small arrays.
--    if (count <= 7)
--      {
--        for (int i = from + 1; i < from + count; i++)
--          for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
--            swap(j, j - 1, array);
--        return;
--      }
--
--    // Determine a good median element.
--    int mid = count / 2;
--    int lo = from;
--    int hi = from + count - 1;
--
--    if (count > 40)
--      { // big arrays, pseudomedian of 9
--        int s = count / 8;
--        lo = med3(lo, lo + s, lo + s + s, array);
--        mid = med3(mid - s, mid, mid + s, array);
--        hi = med3(hi - s - s, hi - s, hi, array);
--      }
--    mid = med3(lo, mid, hi, array);
--
--    int a, b, c, d;
--    int comp;
--
--    // Pull the median element out of the fray, and use it as a pivot.
--    swap(from, mid, array);
--    a = b = from + 1;
--    c = d = hi;
--
--    // Repeatedly move b and c to each other, swapping elements so
--    // that all elements before index b are less than the pivot, and all
--    // elements after index c are greater than the pivot. a and b track
--    // the elements equal to the pivot.
--    while (true)
--      {
--        while (b <= c && (comp = compare(array[b], array[from])) <= 0)
--          {
--            if (comp == 0)
--              {
--                swap(a, b, array);
--                a++;
--              }
--            b++;
--          }
--        while (c >= b && (comp = compare(array[c], array[from])) >= 0)
--          {
--            if (comp == 0)
--              {
--                swap(c, d, array);
--                d--;
--              }
--            c--;
--          }
--        if (b > c)
--          break;
--        swap(b, c, array);
--        b++;
--        c--;
--      }
--
--    // Swap pivot(s) back in place, the recurse on left and right sections.
--    int span;
--    span = Math.min(a - from, b - a);
--    vecswap(from, b - span, span, array);
--
--    span = Math.min(d - c, hi - d - 1);
--    vecswap(b, hi - span + 1, span, array);
--
--    span = b - a;
--    if (span > 1)
--      qsort(array, from, span);
--
--    span = d - c;
--    if (span > 1)
--      qsort(array, hi - span + 1, span);
--  }
--
--  /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
--   *
--   * @param a the long array to sort
-    */
--  public static void sort(long[] a)
-+  public static void sort(int[]a)
-   {
-     qsort(a, 0, a.length);
-   }
- 
--  /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
--   *
--   * @param a the long array to sort
--   * @param fromIndex the first index to sort (inclusive)
--   * @param toIndex the last index to sort (exclusive)
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
--   */
--  public static void sort(long[] a, int fromIndex, int toIndex)
-+  public static void sort(int[] a, int fromIndex, int toIndex)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
--    qsort(a, fromIndex, toIndex - fromIndex);
-+    qsort(a, fromIndex, toIndex);
-   }
- 
--  /**
--   * Finds the index of the median of three array elements.
--   *
--   * @param a the first index
--   * @param b the second index
--   * @param c the third index
--   * @param d the array
--   * @return the index (a, b, or c) which has the middle value of the three
--   */
--  private static int med3(int a, int b, int c, long[] d)
-+  private static int med3(int a, int b, int c, int[]d)
-   {
--    return (d[a] < d[b]
--            ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
--            : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
-+    return d[a] < d[b] ? 
-+               (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
-+	     : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);
-   }
- 
--  /**
--   * Swaps the elements at two locations of an array
--   *
--   * @param i the first index
--   * @param j the second index
--   * @param a the array
--   */
--  private static void swap(int i, int j, long[] a)
-+  private static void swap(int i, int j, int[]a)
-   {
--    long c = a[i];
-+    int c = a[i];
-     a[i] = a[j];
-     a[j] = c;
-   }
- 
--  /**
--   * Swaps two ranges of an array.
--   *
--   * @param i the first range start
--   * @param j the second range start
--   * @param n the element count
--   * @param a the array
--   */
--  private static void vecswap(int i, int j, int n, long[] a)
-+  private static void qsort(int[]a, int start, int n)
-   {
--    for ( ; n > 0; i++, j++, n--)
--      swap(i, j, a);
-+    // use an insertion sort on small arrays
-+    if (n <= 7)
-+      {
-+	for (int i = start + 1; i < start + n; i++)
-+	  for (int j = i; j > 0 && a[j - 1] > a[j]; j--)
-+	    swap(j, j - 1, a);
-+	return;
-+      }
-+
-+    int pm = n / 2;		// small arrays, middle element
-+    if (n > 7)
-+      {
-+	int pl = start;
-+	int pn = start + n - 1;
-+
-+	if (n > 40)
-+	  {			// big arrays, pseudomedian of 9
-+	    int s = n / 8;
-+	    pl = med3(pl, pl + s, pl + 2 * s, a);
-+	    pm = med3(pm - s, pm, pm + s, a);
-+	    pn = med3(pn - 2 * s, pn - s, pn, a);
-+	  }
-+	pm = med3(pl, pm, pn, a);	// mid-size, med of 3
-+      }
-+
-+    int pa, pb, pc, pd, pv;
-+    int r;
-+
-+    pv = start;
-+    swap(pv, pm, a);
-+    pa = pb = start;
-+    pc = pd = start + n - 1;
-+
-+    for (;;)
-+      {
-+	while (pb <= pc && (r = a[pb] - a[pv]) <= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pa, pb, a);
-+		pa++;
-+	      }
-+	    pb++;
-+	  }
-+	while (pc >= pb && (r = a[pc] - a[pv]) >= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pc, pd, a);
-+		pd--;
-+	      }
-+	    pc--;
-+	  }
-+	if (pb > pc)
-+	  break;
-+	swap(pb, pc, a);
-+	pb++;
-+	pc--;
-+      }
-+    int pn = start + n;
-+    int s;
-+    s = Math.min(pa - start, pb - pa);
-+    vecswap(start, pb - s, s, a);
-+    s = Math.min(pd - pc, pn - pd - 1);
-+    vecswap(pb, pn - s, s, a);
-+    if ((s = pb - pa) > 1)
-+      qsort(a, start, s);
-+    if ((s = pd - pc) > 1)
-+      qsort(a, pn - s, s);
-   }
- 
--  /**
--   * Compares two longs in natural order, since a - b is inadequate.
--   *
--   * @param a the first long
--   * @param b the second long
--   * @return &lt; 0, 0, or &gt; 0 accorting to the comparison
--   */
--  private static int compare(long a, long b)
-+  private static void vecswap(int i, int j, int n, int[]a)
-   {
--    return a < b ? -1 : a == b ? 0 : 1;
-+    for (; n > 0; i++, j++, n--)
-+      swap(i, j, a);
-   }
- 
-   /**
--   * Performs a recursive modified quicksort.
-+   * Sort a long array into ascending order. The sort algorithm is an optimised
-+   * quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's
-+   * "Engineering a Sort Function", Software-Practice and Experience, Vol.
-+   * 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
-+   * performance on many arrays that would take quadratic time with a standard
-+   * quicksort.
-    *
-    * @param a the array to sort
--   * @param from the start index (inclusive)
--   * @param count the number of elements to sort
--   */
--  private static void qsort(long[] array, int from, int count)
--  {
--    // Use an insertion sort on small arrays.
--    if (count <= 7)
--      {
--        for (int i = from + 1; i < from + count; i++)
--          for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
--            swap(j, j - 1, array);
--        return;
--      }
--
--    // Determine a good median element.
--    int mid = count / 2;
--    int lo = from;
--    int hi = from + count - 1;
--
--    if (count > 40)
--      { // big arrays, pseudomedian of 9
--        int s = count / 8;
--        lo = med3(lo, lo + s, lo + s + s, array);
--        mid = med3(mid - s, mid, mid + s, array);
--        hi = med3(hi - s - s, hi - s, hi, array);
--      }
--    mid = med3(lo, mid, hi, array);
--
--    int a, b, c, d;
--    int comp;
--
--    // Pull the median element out of the fray, and use it as a pivot.
--    swap(from, mid, array);
--    a = b = from + 1;
--    c = d = hi;
--
--    // Repeatedly move b and c to each other, swapping elements so
--    // that all elements before index b are less than the pivot, and all
--    // elements after index c are greater than the pivot. a and b track
--    // the elements equal to the pivot.
--    while (true)
--      {
--        while (b <= c && (comp = compare(array[b], array[from])) <= 0)
--          {
--            if (comp == 0)
--              {
--                swap(a, b, array);
--                a++;
--              }
--            b++;
--          }
--        while (c >= b && (comp = compare(array[c], array[from])) >= 0)
--          {
--            if (comp == 0)
--              {
--                swap(c, d, array);
--                d--;
--              }
--            c--;
--          }
--        if (b > c)
--          break;
--        swap(b, c, array);
--        b++;
--        c--;
--      }
--
--    // Swap pivot(s) back in place, the recurse on left and right sections.
--    int span;
--    span = Math.min(a - from, b - a);
--    vecswap(from, b - span, span, array);
--
--    span = Math.min(d - c, hi - d - 1);
--    vecswap(b, hi - span + 1, span, array);
--
--    span = b - a;
--    if (span > 1)
--      qsort(array, from, span);
--
--    span = d - c;
--    if (span > 1)
--      qsort(array, hi - span + 1, span);
--  }
--
--  /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
--   *
--   * @param a the float array to sort
-    */
--  public static void sort(float[] a)
-+  public static void sort(long[]a)
-   {
-     qsort(a, 0, a.length);
-   }
- 
--  /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
--   *
--   * @param a the float array to sort
--   * @param fromIndex the first index to sort (inclusive)
--   * @param toIndex the last index to sort (exclusive)
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
--   */
--  public static void sort(float[] a, int fromIndex, int toIndex)
-+  public static void sort(long[] a, int fromIndex, int toIndex)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
--    qsort(a, fromIndex, toIndex - fromIndex);
-+    qsort(a, fromIndex, toIndex);
-   }
- 
--  /**
--   * Finds the index of the median of three array elements.
--   *
--   * @param a the first index
--   * @param b the second index
--   * @param c the third index
--   * @param d the array
--   * @return the index (a, b, or c) which has the middle value of the three
--   */
--  private static int med3(int a, int b, int c, float[] d)
-+  private static int med3(int a, int b, int c, long[]d)
-   {
--    return (Float.compare(d[a], d[b]) < 0
--            ? (Float.compare(d[b], d[c]) < 0 ? b
--               : Float.compare(d[a], d[c]) < 0 ? c : a)
--            : (Float.compare(d[b], d[c]) > 0 ? b
--               : Float.compare(d[a], d[c]) > 0 ? c : a));
-+    return d[a] < d[b] ? 
-+               (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
-+	     : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);
-   }
- 
--  /**
--   * Swaps the elements at two locations of an array
--   *
--   * @param i the first index
--   * @param j the second index
--   * @param a the array
--   */
--  private static void swap(int i, int j, float[] a)
-+  private static void swap(int i, int j, long[]a)
-   {
--    float c = a[i];
-+    long c = a[i];
-     a[i] = a[j];
-     a[j] = c;
-   }
- 
--  /**
--   * Swaps two ranges of an array.
--   *
--   * @param i the first range start
--   * @param j the second range start
--   * @param n the element count
--   * @param a the array
--   */
--  private static void vecswap(int i, int j, int n, float[] a)
-+  private static void qsort(long[]a, int start, int n)
-   {
--    for ( ; n > 0; i++, j++, n--)
--      swap(i, j, a);
-+    // use an insertion sort on small arrays
-+    if (n <= 7)
-+      {
-+	for (int i = start + 1; i < start + n; i++)
-+	  for (int j = i; j > 0 && a[j - 1] > a[j]; j--)
-+	    swap(j, j - 1, a);
-+	return;
-+      }
-+
-+    int pm = n / 2;		// small arrays, middle element
-+    if (n > 7)
-+      {
-+	int pl = start;
-+	int pn = start + n - 1;
-+
-+	if (n > 40)
-+	  {			// big arrays, pseudomedian of 9
-+	    int s = n / 8;
-+	    pl = med3(pl, pl + s, pl + 2 * s, a);
-+	    pm = med3(pm - s, pm, pm + s, a);
-+	    pn = med3(pn - 2 * s, pn - s, pn, a);
-+	  }
-+	pm = med3(pl, pm, pn, a);	// mid-size, med of 3
-+      }
-+
-+    int pa, pb, pc, pd, pv;
-+    long r;
-+
-+    pv = start;
-+    swap(pv, pm, a);
-+    pa = pb = start;
-+    pc = pd = start + n - 1;
-+
-+    for (;;)
-+      {
-+	while (pb <= pc && (r = a[pb] - a[pv]) <= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pa, pb, a);
-+		pa++;
-+	      }
-+	    pb++;
-+	  }
-+	while (pc >= pb && (r = a[pc] - a[pv]) >= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pc, pd, a);
-+		pd--;
-+	      }
-+	    pc--;
-+	  }
-+	if (pb > pc)
-+	  break;
-+	swap(pb, pc, a);
-+	pb++;
-+	pc--;
-+      }
-+    int pn = start + n;
-+    int s;
-+    s = Math.min(pa - start, pb - pa);
-+    vecswap(start, pb - s, s, a);
-+    s = Math.min(pd - pc, pn - pd - 1);
-+    vecswap(pb, pn - s, s, a);
-+    if ((s = pb - pa) > 1)
-+      qsort(a, start, s);
-+    if ((s = pd - pc) > 1)
-+      qsort(a, pn - s, s);
-   }
- 
--  /**
--   * Performs a recursive modified quicksort.
--   *
--   * @param a the array to sort
--   * @param from the start index (inclusive)
--   * @param count the number of elements to sort
--   */
--  private static void qsort(float[] array, int from, int count)
-+  private static void vecswap(int i, int j, int n, long[]a)
-   {
--    // Use an insertion sort on small arrays.
--    if (count <= 7)
--      {
--        for (int i = from + 1; i < from + count; i++)
--          for (int j = i;
--               j > 0 && Float.compare(array[j - 1], array[j]) > 0;
--               j--)
--            {
--              swap(j, j - 1, array);
--            }
--        return;
--      }
--
--    // Determine a good median element.
--    int mid = count / 2;
--    int lo = from;
--    int hi = from + count - 1;
--
--    if (count > 40)
--      { // big arrays, pseudomedian of 9
--        int s = count / 8;
--        lo = med3(lo, lo + s, lo + s + s, array);
--        mid = med3(mid - s, mid, mid + s, array);
--        hi = med3(hi - s - s, hi - s, hi, array);
--      }
--    mid = med3(lo, mid, hi, array);
--
--    int a, b, c, d;
--    int comp;
--
--    // Pull the median element out of the fray, and use it as a pivot.
--    swap(from, mid, array);
--    a = b = from + 1;
--    c = d = hi;
--
--    // Repeatedly move b and c to each other, swapping elements so
--    // that all elements before index b are less than the pivot, and all
--    // elements after index c are greater than the pivot. a and b track
--    // the elements equal to the pivot.
--    while (true)
--      {
--        while (b <= c && (comp = Float.compare(array[b], array[from])) <= 0)
--          {
--            if (comp == 0)
--              {
--                swap(a, b, array);
--                a++;
--              }
--            b++;
--          }
--        while (c >= b && (comp = Float.compare(array[c], array[from])) >= 0)
--          {
--            if (comp == 0)
--              {
--                swap(c, d, array);
--                d--;
--              }
--            c--;
--          }
--        if (b > c)
--          break;
--        swap(b, c, array);
--        b++;
--        c--;
--      }
--
--    // Swap pivot(s) back in place, the recurse on left and right sections.
--    int span;
--    span = Math.min(a - from, b - a);
--    vecswap(from, b - span, span, array);
--
--    span = Math.min(d - c, hi - d - 1);
--    vecswap(b, hi - span + 1, span, array);
--
--    span = b - a;
--    if (span > 1)
--      qsort(array, from, span);
--
--    span = d - c;
--    if (span > 1)
--      qsort(array, hi - span + 1, span);
-+    for (; n > 0; i++, j++, n--)
-+      swap(i, j, a);
-   }
- 
-   /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
-+   * Sort a short array into ascending order. The sort algorithm is an
-+   * optimised quicksort, as described in Jon L. Bentley and M. Douglas
-+   * McIlroy's "Engineering a Sort Function", Software-Practice and Experience,
-+   * Vol. 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
-+   * performance on many arrays that would take quadratic time with a standard
-+   * quicksort.
-    *
--   * @param a the double array to sort
-+   * @param a the array to sort
-    */
--  public static void sort(double[] a)
-+  public static void sort(short[]a)
-   {
-     qsort(a, 0, a.length);
-   }
- 
--  /**
--   * Performs a stable sort on the elements, arranging them according to their
--   * natural order.
--   *
--   * @param a the double array to sort
--   * @param fromIndex the first index to sort (inclusive)
--   * @param toIndex the last index to sort (exclusive)
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; a.length
--   */
--  public static void sort(double[] a, int fromIndex, int toIndex)
-+  public static void sort(short[] a, int fromIndex, int toIndex)
-   {
--    if (fromIndex > toIndex)
--      throw new IllegalArgumentException();
--    qsort(a, fromIndex, toIndex - fromIndex);
-+    qsort(a, fromIndex, toIndex);
-   }
- 
--  /**
--   * Finds the index of the median of three array elements.
--   *
--   * @param a the first index
--   * @param b the second index
--   * @param c the third index
--   * @param d the array
--   * @return the index (a, b, or c) which has the middle value of the three
--   */
--  private static int med3(int a, int b, int c, double[] d)
-+  private static int med3(int a, int b, int c, short[]d)
-   {
--    return (Double.compare(d[a], d[b]) < 0
--            ? (Double.compare(d[b], d[c]) < 0 ? b
--               : Double.compare(d[a], d[c]) < 0 ? c : a)
--            : (Double.compare(d[b], d[c]) > 0 ? b
--               : Double.compare(d[a], d[c]) > 0 ? c : a));
-+    return d[a] < d[b] ? 
-+               (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
-+	     : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);
-   }
- 
--  /**
--   * Swaps the elements at two locations of an array
--   *
--   * @param i the first index
--   * @param j the second index
--   * @param a the array
--   */
--  private static void swap(int i, int j, double[] a)
-+  private static void swap(int i, int j, short[]a)
-   {
--    double c = a[i];
-+    short c = a[i];
-     a[i] = a[j];
-     a[j] = c;
-   }
- 
--  /**
--   * Swaps two ranges of an array.
--   *
--   * @param i the first range start
--   * @param j the second range start
--   * @param n the element count
--   * @param a the array
--   */
--  private static void vecswap(int i, int j, int n, double[] a)
-+  private static void qsort(short[]a, int start, int n)
-+  {
-+    // use an insertion sort on small arrays
-+    if (n <= 7)
-+      {
-+	for (int i = start + 1; i < start + n; i++)
-+	  for (int j = i; j > 0 && a[j - 1] > a[j]; j--)
-+	    swap(j, j - 1, a);
-+	return;
-+      }
-+
-+    int pm = n / 2;		// small arrays, middle element
-+    if (n > 7)
-+      {
-+	int pl = start;
-+	int pn = start + n - 1;
-+
-+	if (n > 40)
-+	  {			// big arrays, pseudomedian of 9
-+	    int s = n / 8;
-+	    pl = med3(pl, pl + s, pl + 2 * s, a);
-+	    pm = med3(pm - s, pm, pm + s, a);
-+	    pn = med3(pn - 2 * s, pn - s, pn, a);
-+	  }
-+	pm = med3(pl, pm, pn, a);	// mid-size, med of 3
-+      }
-+
-+    int pa, pb, pc, pd, pv;
-+    int r;
-+
-+    pv = start;
-+    swap(pv, pm, a);
-+    pa = pb = start;
-+    pc = pd = start + n - 1;
-+
-+    for (;;)
-+      {
-+	while (pb <= pc && (r = a[pb] - a[pv]) <= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pa, pb, a);
-+		pa++;
-+	      }
-+	    pb++;
-+	  }
-+	while (pc >= pb && (r = a[pc] - a[pv]) >= 0)
-+	  {
-+	    if (r == 0)
-+	      {
-+		swap(pc, pd, a);
-+		pd--;
-+	      }
-+	    pc--;
-+	  }
-+	if (pb > pc)
-+	  break;
-+	swap(pb, pc, a);
-+	pb++;
-+	pc--;
-+      }
-+    int pn = start + n;
-+    int s;
-+    s = Math.min(pa - start, pb - pa);
-+    vecswap(start, pb - s, s, a);
-+    s = Math.min(pd - pc, pn - pd - 1);
-+    vecswap(pb, pn - s, s, a);
-+    if ((s = pb - pa) > 1)
-+      qsort(a, start, s);
-+    if ((s = pd - pc) > 1)
-+      qsort(a, pn - s, s);
-+  }
-+
-+  private static void vecswap(int i, int j, int n, short[]a)
-   {
--    for ( ; n > 0; i++, j++, n--)
-+    for (; n > 0; i++, j++, n--)
-       swap(i, j, a);
-   }
- 
-   /**
--   * Performs a recursive modified quicksort.
--   *
--   * @param a the array to sort
--   * @param from the start index (inclusive)
--   * @param count the number of elements to sort
--   */
--  private static void qsort(double[] array, int from, int count)
--  {
--    // Use an insertion sort on small arrays.
--    if (count <= 7)
-+   * The bulk of the work for the object sort routines.  In general,
-+   * the code attempts to be simple rather than fast, the idea being
-+   * that a good optimising JIT will be able to optimise it better
-+   * than I can, and if I try it will make it more confusing for the
-+   * JIT.  
-+   */
-+  private static void mergeSort(Object[]a, int from, int to, Comparator c)
-+  {
-+    // First presort the array in chunks of length 6 with insertion sort. 
-+    // mergesort would give too much overhead for this length.
-+    for (int chunk = from; chunk < to; chunk += 6)
-+      {
-+	int end = Math.min(chunk + 6, to);
-+	for (int i = chunk + 1; i < end; i++)
-+	  {
-+	    if (c.compare(a[i - 1], a[i]) > 0)
-+	      {
-+		// not already sorted
-+		int j = i;
-+		Object elem = a[j];
-+		do
-+		  {
-+		    a[j] = a[j - 1];
-+		    j--;
-+		  }
-+		while (j > chunk && c.compare(a[j - 1], elem) > 0);
-+		a[j] = elem;
-+	      }
-+	  }
-+      }
-+
-+    int len = to - from;
-+    // If length is smaller or equal 6 we are done.
-+    if (len <= 6)
-+      return;
-+
-+    Object[]src = a;
-+    Object[]dest = new Object[len];
-+    Object[]t = null;		// t is used for swapping src and dest
-+
-+    // The difference of the fromIndex of the src and dest array.
-+    int srcDestDiff = -from;
-+
-+    // The merges are done in this loop
-+    for (int size = 6; size < len; size <<= 1)
-+      {
-+	for (int start = from; start < to; start += size << 1)
-+	  {
-+	    // mid ist the start of the second sublist;
-+	    // end the start of the next sublist (or end of array).
-+	    int mid = start + size;
-+	    int end = Math.min(to, mid + size);
-+
-+	    // The second list is empty or the elements are already in
-+	    // order - no need to merge
-+	    if (mid >= end || c.compare(src[mid - 1], src[mid]) <= 0)
-+	      {
-+		System.arraycopy(src, start,
-+				 dest, start + srcDestDiff, end - start);
-+
-+		// The two halves just need swapping - no need to merge
-+	      }
-+	    else if (c.compare(src[start], src[end - 1]) > 0)
-+	      {
-+		System.arraycopy(src, start,
-+				 dest, end - size + srcDestDiff, size);
-+		System.arraycopy(src, mid,
-+				 dest, start + srcDestDiff, end - mid);
-+
-+	      }
-+	    else
-+	      {
-+		// Declare a lot of variables to save repeating
-+		// calculations.  Hopefully a decent JIT will put these
-+		// in registers and make this fast
-+		int p1 = start;
-+		int p2 = mid;
-+		int i = start + srcDestDiff;
-+
-+		// The main merge loop; terminates as soon as either
-+		// half is ended
-+		while (p1 < mid && p2 < end)
-+		  {
-+		    dest[i++] =
-+		      src[c.compare(src[p1], src[p2]) <= 0 ? p1++ : p2++];
-+		  }
-+
-+		// Finish up by copying the remainder of whichever half
-+		// wasn't finished.
-+		if (p1 < mid)
-+		  System.arraycopy(src, p1, dest, i, mid - p1);
-+		else
-+		  System.arraycopy(src, p2, dest, i, end - p2);
-+	      }
-+	  }
-+	// swap src and dest ready for the next merge
-+	t = src;
-+	src = dest;
-+	dest = t;
-+	from += srcDestDiff;
-+	to += srcDestDiff;
-+	srcDestDiff = -srcDestDiff;
-+      }
-+
-+    // make sure the result ends up back in the right place.  Note
-+    // that src and dest may have been swapped above, so src 
-+    // contains the sorted array.
-+    if (src != a)
-       {
--        for (int i = from + 1; i < from + count; i++)
--          for (int j = i;
--               j > 0 && Double.compare(array[j - 1], array[j]) > 0;
--               j--)
--            {
--              swap(j, j - 1, array);
--            }
--        return;
--      }
--
--    // Determine a good median element.
--    int mid = count / 2;
--    int lo = from;
--    int hi = from + count - 1;
--
--    if (count > 40)
--      { // big arrays, pseudomedian of 9
--        int s = count / 8;
--        lo = med3(lo, lo + s, lo + s + s, array);
--        mid = med3(mid - s, mid, mid + s, array);
--        hi = med3(hi - s - s, hi - s, hi, array);
--      }
--    mid = med3(lo, mid, hi, array);
--
--    int a, b, c, d;
--    int comp;
--
--    // Pull the median element out of the fray, and use it as a pivot.
--    swap(from, mid, array);
--    a = b = from + 1;
--    c = d = hi;
--
--    // Repeatedly move b and c to each other, swapping elements so
--    // that all elements before index b are less than the pivot, and all
--    // elements after index c are greater than the pivot. a and b track
--    // the elements equal to the pivot.
--    while (true)
--      {
--        while (b <= c && (comp = Double.compare(array[b], array[from])) <= 0)
--          {
--            if (comp == 0)
--              {
--                swap(a, b, array);
--                a++;
--              }
--            b++;
--          }
--        while (c >= b && (comp = Double.compare(array[c], array[from])) >= 0)
--          {
--            if (comp == 0)
--              {
--                swap(c, d, array);
--                d--;
--              }
--            c--;
--          }
--        if (b > c)
--          break;
--        swap(b, c, array);
--        b++;
--        c--;
--      }
--
--    // Swap pivot(s) back in place, the recurse on left and right sections.
--    int span;
--    span = Math.min(a - from, b - a);
--    vecswap(from, b - span, span, array);
--
--    span = Math.min(d - c, hi - d - 1);
--    vecswap(b, hi - span + 1, span, array);
--
--    span = b - a;
--    if (span > 1)
--      qsort(array, from, span);
--
--    span = d - c;
--    if (span > 1)
--      qsort(array, hi - span + 1, span);
-+	// Note that from == 0.
-+	System.arraycopy(src, 0, a, srcDestDiff, to);
-+      }
-   }
- 
-   /**
-@@ -2135,19 +1972,18 @@
-    * guaranteed to be stable, that is, equal elements will not be reordered.
-    * The sort algorithm is a mergesort with the merge omitted if the last
-    * element of one half comes before the first element of the other half. This
--   * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
-+   * algorithm gives guaranteed O(nlog(n)) time, at the expense of making a
-    * copy of the array.
-    *
-    * @param a the array to be sorted
--   * @throws ClassCastException if any two elements are not mutually
--   *         comparable
--   * @throws NullPointerException if an element is null (since
--   *         null.compareTo cannot work)
--   * @see Comparable
-+   * @exception ClassCastException if any two elements are not mutually
-+   *   comparable
-+   * @exception NullPointerException if an element is null (since
-+   *   null.compareTo cannot work)
-    */
--  public static void sort(Object[] a)
-+  public static void sort(Object[]a)
-   {
--    sort(a, 0, a.length, null);
-+    mergeSort(a, 0, a.length, defaultComparator);
-   }
- 
-   /**
-@@ -2155,20 +1991,17 @@
-    * guaranteed to be stable, that is, equal elements will not be reordered.
-    * The sort algorithm is a mergesort with the merge omitted if the last
-    * element of one half comes before the first element of the other half. This
--   * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
-+   * algorithm gives guaranteed O(nlog(n)) time, at the expense of making a
-    * copy of the array.
-    *
-    * @param a the array to be sorted
--   * @param c a Comparator to use in sorting the array; or null to indicate
--   *        the elements' natural order
--   * @throws ClassCastException if any two elements are not mutually
--   *         comparable by the Comparator provided
--   * @throws NullPointerException if a null element is compared with natural
--   *         ordering (only possible when c is null)
-+   * @param c a Comparator to use in sorting the array
-+   * @exception ClassCastException if any two elements are not mutually
-+   *   comparable by the Comparator provided
-    */
--  public static void sort(Object[] a, Comparator c)
-+  public static void sort(Object[]a, Comparator c)
-   {
--    sort(a, 0, a.length, c);
-+    mergeSort(a, 0, a.length, c);
-   }
- 
-   /**
-@@ -2176,23 +2009,24 @@
-    * guaranteed to be stable, that is, equal elements will not be reordered.
-    * The sort algorithm is a mergesort with the merge omitted if the last
-    * element of one half comes before the first element of the other half. This
--   * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
-+   * algorithm gives guaranteed O(nlog(n)) time, at the expense of making a
-    * copy of the array.
-    *
-    * @param a the array to be sorted
--   * @param fromIndex the index of the first element to be sorted
--   * @param toIndex the index of the last element to be sorted plus one
--   * @throws ClassCastException if any two elements are not mutually
--   *         comparable
--   * @throws NullPointerException if an element is null (since
--   *         null.compareTo cannot work)
--   * @throws ArrayIndexOutOfBoundsException, if fromIndex and toIndex
--   *         are not in range.
--   * @throws IllegalArgumentException if fromIndex > toIndex
-+   * @param fromIndex the index of the first element to be sorted.
-+   * @param toIndex the index of the last element to be sorted plus one.
-+   * @exception ClassCastException if any two elements are not mutually
-+   *   comparable by the Comparator provided
-+   * @exception ArrayIndexOutOfBoundsException, if fromIndex and toIndex
-+   *   are not in range.
-+   * @exception IllegalArgumentException if fromIndex > toIndex
-    */
--  public static void sort(Object[] a, int fromIndex, int toIndex)
-+  public static void sort(Object[]a, int fromIndex, int toIndex)
-   {
--    sort(a, fromIndex, toIndex, null);
-+    if (fromIndex > toIndex)
-+      throw new IllegalArgumentException("fromIndex " + fromIndex
-+					 + " > toIndex " + toIndex);
-+    mergeSort(a, fromIndex, toIndex, defaultComparator);
-   }
- 
-   /**
-@@ -2200,197 +2034,56 @@
-    * guaranteed to be stable, that is, equal elements will not be reordered.
-    * The sort algorithm is a mergesort with the merge omitted if the last
-    * element of one half comes before the first element of the other half. This
--   * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
-+   * algorithm gives guaranteed O(nlog(n)) time, at the expense of making a
-    * copy of the array.
-    *
-    * @param a the array to be sorted
--   * @param fromIndex the index of the first element to be sorted
--   * @param toIndex the index of the last element to be sorted plus one
--   * @param c a Comparator to use in sorting the array; or null to indicate
--   *        the elements' natural order
--   * @throws ClassCastException if any two elements are not mutually
--   *         comparable by the Comparator provided
--   * @throws ArrayIndexOutOfBoundsException, if fromIndex and toIndex
--   *         are not in range.
--   * @throws IllegalArgumentException if fromIndex > toIndex
--   * @throws NullPointerException if a null element is compared with natural
--   *         ordering (only possible when c is null)
-+   * @param fromIndex the index of the first element to be sorted.
-+   * @param toIndex the index of the last element to be sorted plus one.
-+   * @param c a Comparator to use in sorting the array
-+   * @exception ClassCastException if any two elements are not mutually
-+   *   comparable by the Comparator provided
-+   * @exception ArrayIndexOutOfBoundsException, if fromIndex and toIndex
-+   *   are not in range.
-+   * @exception IllegalArgumentException if fromIndex > toIndex
-    */
--  public static void sort(Object[] a, int fromIndex, int toIndex, Comparator c)
-+  public static void sort(Object[]a, int fromIndex, int toIndex, Comparator c)
-   {
-     if (fromIndex > toIndex)
-       throw new IllegalArgumentException("fromIndex " + fromIndex
--                                         + " > toIndex " + toIndex);
--
--    // In general, the code attempts to be simple rather than fast, the
--    // idea being that a good optimising JIT will be able to optimise it
--    // better than I can, and if I try it will make it more confusing for
--    // the JIT. First presort the array in chunks of length 6 with insertion
--    // sort. A mergesort would give too much overhead for this length.
--    for (int chunk = fromIndex; chunk < toIndex; chunk += 6)
--      {
--        int end = Math.min(chunk + 6, toIndex);
--        for (int i = chunk + 1; i < end; i++)
--          {
--            if (Collections.compare(a[i - 1], a[i], c) > 0)
--              {
--                // not already sorted
--                int j = i;
--                Object elem = a[j];
--                do
--                  {
--                    a[j] = a[j - 1];
--                    j--;
--                  }
--                while (j > chunk
--                       && Collections.compare(a[j - 1], elem, c) > 0);
--                a[j] = elem;
--              }
--          }
--      }
--
--    int len = toIndex - fromIndex;
--    // If length is smaller or equal 6 we are done.
--    if (len <= 6)
--      return;
--
--    Object[] src = a;
--    Object[] dest = new Object[len];
--    Object[] t = null; // t is used for swapping src and dest
--
--    // The difference of the fromIndex of the src and dest array.
--    int srcDestDiff = -fromIndex;
--
--    // The merges are done in this loop
--    for (int size = 6; size < len; size <<= 1)
--      {
--        for (int start = fromIndex; start < toIndex; start += size << 1)
--          {
--            // mid is the start of the second sublist;
--            // end the start of the next sublist (or end of array).
--            int mid = start + size;
--            int end = Math.min(toIndex, mid + size);
--
--            // The second list is empty or the elements are already in
--            // order - no need to merge
--            if (mid >= end
--                || Collections.compare(src[mid - 1], src[mid], c) <= 0)
--              {
--                System.arraycopy(src, start,
--                                 dest, start + srcDestDiff, end - start);
--
--                // The two halves just need swapping - no need to merge
--              }
--            else if (Collections.compare(src[start], src[end - 1], c) > 0)
--              {
--                System.arraycopy(src, start,
--                                 dest, end - size + srcDestDiff, size);
--                System.arraycopy(src, mid,
--                                 dest, start + srcDestDiff, end - mid);
--
--              }
--            else
--              {
--                // Declare a lot of variables to save repeating
--                // calculations.  Hopefully a decent JIT will put these
--                // in registers and make this fast
--                int p1 = start;
--                int p2 = mid;
--                int i = start + srcDestDiff;
--
--                // The main merge loop; terminates as soon as either
--                // half is ended
--                while (p1 < mid && p2 < end)
--                  {
--                    dest[i++] =
--                      src[(Collections.compare(src[p1], src[p2], c) <= 0
--                           ? p1++ : p2++)];
--                  }
--
--                // Finish up by copying the remainder of whichever half
--                // wasn't finished.
--                if (p1 < mid)
--                  System.arraycopy(src, p1, dest, i, mid - p1);
--                else
--                  System.arraycopy(src, p2, dest, i, end - p2);
--              }
--          }
--        // swap src and dest ready for the next merge
--        t = src;
--        src = dest;
--        dest = t;
--        fromIndex += srcDestDiff;
--        toIndex += srcDestDiff;
--        srcDestDiff = -srcDestDiff;
--      }
--
--    // make sure the result ends up back in the right place.  Note
--    // that src and dest may have been swapped above, so src
--    // contains the sorted array.
--    if (src != a)
--      {
--        // Note that fromIndex == 0.
--        System.arraycopy(src, 0, a, srcDestDiff, toIndex);
--      }
-+					 + " > toIndex " + toIndex);
-+    mergeSort(a, fromIndex, toIndex, c);
-   }
- 
--
 -// asList
    /**
     * Returns a list "view" of the specified array. This method is intended to
     * make it easy to use the Collections API with existing array-based APIs and
--   * programs. Changes in the list or the array show up in both places. The
--   * list does not support element addition or removal, but does permit
--   * value modification. The returned list implements both Serializable and
--   * RandomAccess.
-+   * programs.
-    *
-    * @param a the array to return a view of
--   * @return a fixed-size list, changes to which "write through" to the array
--   * @see Serializable
--   * @see RandomAccess
--   * @see Arrays.ArrayList
-+   * @returns a fixed-size list, changes to which "write through" to the array
-    */
--  public static List asList(final Object[] a)
-+  public static List asList(final Object[]a)
-   {
--    return new Arrays.ArrayList(a);
-+    if (a == null)
-+      {
-+	throw new NullPointerException();
-+      }
-+
-+    return new ListImpl(a);
-   }
- 
-+
-   /**
--   * Inner class used by {@link #asList(Object[])} to provide a list interface
--   * to an array. The name, though it clashes with java.util.ArrayList, is
--   * Sun's choice for Serialization purposes. Element addition and removal
--   * is prohibited, but values can be modified.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   * @status updated to 1.4
-+   * Inner class used by asList(Object[]) to provide a list interface
-+   * to an array. The methods are all simple enough to be self documenting.
-+   * Note: When Sun fully specify serialized forms, this class will have to
-+   * be renamed.
-    */
--  private static final class ArrayList extends AbstractList
--    implements Serializable, RandomAccess
-+  private static class ListImpl extends AbstractList
-   {
--    // We override the necessary methods, plus others which will be much
--    // more efficient with direct iteration rather than relying on iterator().
--
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = -2764017481108945198L;
--
--    /**
--     * The array we are viewing.
--     * @serial the array
--     */
--    private final Object[] a;
--
--    /**
--     * Construct a list view of the array.
--     * @param a the array to view
--     * @throws NullPointerException if a is null
--     */
--    ArrayList(Object[] a)
-+    ListImpl(Object[]a)
-     {
--      // We have to explicitly check.
--      if (a == null)
--        throw new NullPointerException();
-       this.a = a;
-     }
- 
-@@ -2411,45 +2104,6 @@
-       return old;
-     }
- 
--    public boolean contains(Object o)
--    {
--      return lastIndexOf(o) >= 0;
--    }
--
--    public int indexOf(Object o)
--    {
--      int size = a.length;
--      for (int i = 0; i < size; i++)
--        if (equals(o, a[i]))
--          return i;
--      return -1;
--    }
--
--    public int lastIndexOf(Object o)
--    {
--      int i = a.length;
--      while (--i >= 0)
--        if (equals(o, a[i]))
--          return i;
--      return -1;
--    }
--
--    public Object[] toArray()
--    {
--      return (Object[]) a.clone();
--    }
--
--    public Object[] toArray(Object[] array)
--    {
--      int size = a.length;
--      if (array.length < size)
--        array = (Object[])
--          Array.newInstance(array.getClass().getComponentType(), size);
--      else if (array.length > size)
--        array[size] = null;
--
--      System.arraycopy(a, 0, array, 0, size);
--      return array;
--    }
-+    private Object[] a;
-   }
- }
Index: compare/java.util.Collections.diff
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/java/compare/java.util.Collections.diff,v
retrieving revision 1.5
diff -u -r1.5 java.util.Collections.diff
--- compare/java.util.Collections.diff 2001/11/07 01:23:49 1.5
+++ compare/java.util.Collections.diff 2001/12/16 00:14:01
@@ -1,124 +1,48 @@
 --- /home/tromey/gnu/egcs/classpath/classpath/java/util/Collections.java	Fri Nov  2 09:28:56 2001
-+++ java/util/Collections.java	Fri Nov  2 21:44:51 2001
-@@ -25,6 +25,10 @@
- executable file might be covered by the GNU General Public License. */
- 
- 
-+// TO DO:
-+// ~ Serialization is very much broken. Blame Sun for not specifying it.
-+// ~ The synchronized* and unmodifiable* methods don't have doc-comments.
-+
- package java.util;
- 
- import java.io.Serializable;
-@@ -36,54 +40,10 @@
-  * are unaware of collections, a method to return a list which consists of
-  * multiple copies of one element, and methods which "wrap" collections to give
-  * them extra properties, such as thread-safety and unmodifiability.
-- * <p>
-- *
-- * All methods which take a collection throw a {@link NullPointerException} if
-- * that collection is null. Algorithms which can change a collection may, but
-- * are not required, to throw the {@link UnsupportedOperationException} that
-- * the underlying collection would throw during an attempt at modification.
-- * For example,
-- * <code>Collections.singleton("").addAll(Collections.EMPTY_SET)<code>
-- * does not throw a exception, even though addAll is an unsupported operation
-- * on a singleton; the reason for this is that addAll did not attempt to
-- * modify the set.
-- *
-- * @author Original author unknown
-- * @author Eric Blake <ebb9@email.byu.edu>
-- * @see Collection
-- * @see Set
-- * @see List
-- * @see Map
-- * @see Arrays
-- * @since 1.2
-- * @status updated to 1.4
-  */
- public class Collections
- {
-   /**
--   * Constant used to decide cutoff for when a non-RandomAccess list should
--   * be treated as sequential-access. Basically, quadratic behavior is
--   * acceptible for small lists when the overhead is so small in the first
--   * place. I arbitrarily set it to 16, so it may need some tuning.
--   */
--  private static final int LARGE_LIST_SIZE = 16;
--
--  /**
--   * Determines if a list should be treated as a sequential-access one.
--   * Rather than the old method of JDK 1.3 of assuming only instanceof
--   * AbstractSequentialList should be sequential, this uses the new method
--   * of JDK 1.4 of assuming anything that does NOT implement RandomAccess
--   * and exceeds a large (unspecified) size should be sequential.
--   *
--   * @param l the list to check
--   * @return true if it should be treated as sequential-access
--   */
--  private static boolean isSequential(List l)
--  {
--    return ! (l instanceof RandomAccess) && l.size() > LARGE_LIST_SIZE;
--  }
--
--  /**
-    * This class is non-instantiable.
++++ java/util/Collections.java	Sat Dec 15 09:16:02 2001
+@@ -49,6 +49,7 @@
+  * modify the set.
+  *
+  * @author Original author unknown
++ * @author Bryce McKinlay
+  * @author Eric Blake <ebb9@email.byu.edu>
+  * @see Collection
+  * @see Set
+@@ -96,6 +97,24 @@
     */
-   private Collections()
-@@ -91,513 +51,200 @@
-   }
+   public static final Set EMPTY_SET = new EmptySet();
  
++  private static final Iterator EMPTY_ITERATOR = new Iterator()
++    {
++      public boolean hasNext()
++      {
++	return false;
++      }
++
++      public Object next()
++      {
++	throw new NoSuchElementException();
++      }
++
++      public void remove()
++      {
++	throw new UnsupportedOperationException();
++      }
++    };
++
    /**
--   * An immutable, serializable, empty Set.
--   * @see Serializable
--   */
--  public static final Set EMPTY_SET = new EmptySet();
--
--  /**
--   * The implementation of {@link #EMPTY_SET}. This class name is required
--   * for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
-+   * An immutable, empty Set.
-+   * Note: This implementation isn't Serializable, although it should be by the
-+   * spec.
-    */
--  private static final class EmptySet extends AbstractSet
--    implements Serializable
-+  public static final Set EMPTY_SET = new AbstractSet()
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = 1582296315990362920L;
--
--    /**
--     * A private constructor adds overhead.
--     */
--    EmptySet()
--    {
--    }
--
--    /**
--     * The size: always 0!
--     */
-     public int size()
-     {
-       return 0;
-     }
- 
--    /**
--     * Returns an iterator that does not iterate.
--     */
+    * The implementation of {@link #EMPTY_SET}. This class name is required
+    * for compatibility with Sun's JDK serializability.
+@@ -128,94 +147,9 @@
+     /**
+      * Returns an iterator that does not iterate.
+      */
 -    // This is really cheating! I think it's perfectly valid, though.
-+    // This is really cheating! I think it's perfectly valid, though - the
-+    // more conventional code is here, commented out, in case anyone disagrees.
      public Iterator iterator()
      {
-       return EMPTY_LIST.iterator();
-     }
- 
+-      return EMPTY_LIST.iterator();
+-    }
+-
 -    // The remaining methods are optional, but provide a performance
 -    // advantage by not allocating unnecessary iterators in AbstractSet.
 -    /**
@@ -201,73 +125,11 @@
 -    public String toString()
 -    {
 -      return "[]";
--    }
--  } // class EmptySet
--
--  /**
--   * An immutable, serializable, empty List, which implements RandomAccess.
--   * @see Serializable
--   * @see RandomAccess
--   */
--  public static final List EMPTY_LIST = new EmptyList();
--
--  /**
--   * The implementation of {@link #EMPTY_LIST}. This class name is required
--   * for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
-+    // public Iterator iterator() {
-+    //   return new Iterator() {
-+    // 
-+    //     public boolean hasNext() {
-+    //       return false;
-+    //     }
-+    // 
-+    //     public Object next() {
-+    //       throw new NoSuchElementException();
-+    //     }
-+    // 
-+    //     public void remove() {
-+    //       throw new UnsupportedOperationException();
-+    //     }
-+    //   };
-+    // }
-+
-+  };
-+
-+  /**
-+   * An immutable, empty List.
-+   * Note: This implementation isn't serializable, although it should be by the
-+   * spec.
-    */
--  private static final class EmptyList extends AbstractList
--    implements Serializable, RandomAccess
-+  public static final List EMPTY_LIST = new AbstractList()
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = 8842843931221139166L;
--
--    /**
--     * A private constructor adds overhead.
--     */
--    EmptyList()
--    {
--    }
--
--    /**
--     * The size is always 0.
--     */
-     public int size()
-     {
-       return 0;
++      return EMPTY_ITERATOR;
      }
+   } // class EmptySet
  
--    /**
--     * No matter the index, it is out of bounds.
--     */
-     public Object get(int index)
+@@ -262,106 +196,15 @@
      {
        throw new IndexOutOfBoundsException();
      }
@@ -290,9 +152,12 @@
 -      return c.isEmpty();
 -    }
 -
--    /**
++    
+     /**
 -     * Equal only if the other set is empty.
--     */
++     * Returns an iterator that does not iterate. Optional, but avoids 
++     * allocation of an iterator in AbstractList.
+      */
 -    public boolean equals(Object o)
 -    {
 -      return o instanceof List && ((List) o).isEmpty();
@@ -368,51 +233,18 @@
 -     * The string never changes.
 -     */
 -    public String toString()
--    {
++    public Iterator iterator()
+     {
 -      return "[]";
 -    }
--  } // class EmptyList
--
--  /**
--   * An immutable, serializable, empty Map.
--   * @see Serializable
--   */
--  public static final Map EMPTY_MAP = new EmptyMap();
-+  };
++      return EMPTY_ITERATOR;
++    }    
+   } // class EmptyList
  
    /**
--   * The implementation of {@link #EMPTY_MAP}. This class name is required
--   * for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
-+   * An immutable, empty Map.
-+   * Note: This implementation isn't serializable, although it should be by the
-+   * spec.
-    */
--  private static final class EmptyMap extends AbstractMap
--    implements Serializable
-+  public static final Map EMPTY_MAP = new AbstractMap()
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = 6428348081105594320L;
--
--    /**
--     * A private constructor adds overhead.
--     */
--    EmptyMap()
--    {
--    }
--
--    /**
--     * There are no entries.
--     */
-     public Set entrySet()
-     {
+@@ -399,64 +242,6 @@
        return EMPTY_SET;
      }
-+  };
  
 -    // The remaining methods are optional, but provide a performance
 -    // advantage by not allocating unnecessary iterators in AbstractMap.
@@ -471,23 +303,14 @@
 -    {
 -      return null;
 -    }
--
--    /**
--     * Size is always 0.
--     */
--    public int size()
--    {
--      return 0;
--    }
 -
--    /**
--     * No entries. Technically, EMPTY_SET, while more specific than a general
--     * Collection, will work. Besides, that's what the JDK uses!
--     */
--    public Collection values()
--    {
--      return EMPTY_SET;
--    }
+     /**
+      * Size is always 0.
+      */
+@@ -473,17 +258,8 @@
+     {
+       return EMPTY_SET;
+     }
 -
 -    /**
 -     * The string never changes.
@@ -496,4184 +319,25 @@
 -    {
 -      return "[]";
 -    }
--  } // class EmptyMap
--
+   } // class EmptyMap
+ 
 -
    /**
     * Compare two objects with or without a Comparator. If c is null, uses the
     * natural ordering. Slightly slower than doing it inline if the JVM isn't
-    * clever, but worth it for removing a duplicate of the search code.
--   * Note: This code is also used in Arrays (for sort as well as search).
-+   * Note: This same code is used in Arrays (for sort as well as search)
-+   */
-+  private static int compare(Object o1, Object o2, Comparator c)
-+  {
-+    if (c == null)
-+      {
-+	return ((Comparable) o1).compareTo(o2);
-+      }
-+    else
-+      {
-+	return c.compare(o1, o2);
-+      }
-+  }
-+
-+  /**
-+   * The hard work for the search routines. If the Comparator given is null,
-+   * uses the natural ordering of the elements.
-    */
--  static final int compare(Object o1, Object o2, Comparator c)
-+  private static int search(List l, Object key, final Comparator c)
-   {
--    return c == null ? ((Comparable) o1).compareTo(o2) : c.compare(o1, o2);
-+    int pos = 0;
-+
-+    // We use a linear search using an iterator if we can guess that the list
-+    // is sequential-access.
-+    if (l instanceof AbstractSequentialList)
-+      {
-+	ListIterator itr = l.listIterator();
-+    	for (int i = l.size() - 1; i >= 0; --i)
-+	  {
-+	    final int d = compare(key, itr.next(), c);
-+	    if (d == 0)
-+	      {
-+		return pos;
-+	      }
-+	    else if (d < 0)
-+	      {
-+		return -pos - 1;
-+	      }
-+	    pos++;
-+	  }
-+
-+	// We assume the list is random-access, and use a binary search
-+      }
-+    else
-+      {
-+	int low = 0;
-+	int hi = l.size() - 1;
-+	while (low <= hi)
-+	  {
-+	    pos = (low + hi) >> 1;
-+	    final int d = compare(key, l.get(pos), c);
-+	    if (d == 0)
-+	      {
-+		return pos;
-+	      }
-+	    else if (d < 0)
-+	      {
-+		hi = pos - 1;
-+	      }
-+	    else
-+	      {
-+		low = ++pos;	// This gets the insertion point right on the last loop
-+	      }
-+	  }
-+      }
-+
-+    // If we failed to find it, we do the same whichever search we did.
-+    return -pos - 1;
-   }
- 
-   /**
-    * Perform a binary search of a List for a key, using the natural ordering of
-    * the elements. The list must be sorted (as by the sort() method) - if it is
--   * not, the behavior of this method is undefined, and may be an infinite
-+   * not, the behaviour of this method is undefined, and may be an infinite
-    * loop. Further, the key must be comparable with every item in the list. If
--   * the list contains the key more than once, any one of them may be found.
--   * <p>
--   *
--   * This algorithm behaves in log(n) time for {@link RandomAccess} lists,
--   * and uses a linear search with O(n) link traversals and log(n) comparisons
--   * with {@link AbstractSequentialList} lists. Note: although the
-+   * the list contains the key more than once, any one of them may be found. To
-+   * avoid pathological behaviour on sequential-access lists, a linear search
-+   * is used if (l instanceof AbstractSequentialList). Note: although the
-    * specification allows for an infinite loop if the list is unsorted, it will
-    * not happen in this (Classpath) implementation.
-    *
-    * @param l the list to search (must be sorted)
-    * @param key the value to search for
--   * @return the index at which the key was found, or -n-1 if it was not
--   *         found, where n is the index of the first value higher than key or
--   *         a.length if there is no such value
--   * @throws ClassCastException if key could not be compared with one of the
--   *         elements of l
--   * @throws NullPointerException if a null element has compareTo called
--   * @see #sort(List)
-+   * @returns the index at which the key was found, or -n-1 if it was not
-+   *   found, where n is the index of the first value higher than key or
-+   *   a.length if there is no such value.
-+   * @exception ClassCastException if key could not be compared with one of the
-+   *   elements of l
-+   * @exception NullPointerException if a null element has compareTo called
-    */
-   public static int binarySearch(List l, Object key)
-   {
--    return binarySearch(l, key, null);
-+    return search(l, key, null);
-   }
- 
-   /**
-    * Perform a binary search of a List for a key, using a supplied Comparator.
-    * The list must be sorted (as by the sort() method with the same Comparator)
--   * - if it is not, the behavior of this method is undefined, and may be an
-+   * - if it is not, the behaviour of this method is undefined, and may be an
-    * infinite loop. Further, the key must be comparable with every item in the
-    * list. If the list contains the key more than once, any one of them may be
--   * found. If the comparator is null, the elements' natural ordering is used.
--   * <p>
--   *
--   * This algorithm behaves in log(n) time for {@link RandomAccess} lists,
--   * and uses a linear search with O(n) link traversals and log(n) comparisons
--   * with {@link AbstractSequentialList} lists. Note: although the
--   * specification allows for an infinite loop if the list is unsorted, it will
--   * not happen in this (Classpath) implementation.
-+   * found. To avoid pathological behaviour on sequential-access lists, a
-+   * linear search is used if (l instanceof AbstractSequentialList). Note:
-+   * although the specification allows for an infinite loop if the list is
-+   * unsorted, it will not happen in this (Classpath) implementation.
-    *
-    * @param l the list to search (must be sorted)
-    * @param key the value to search for
-    * @param c the comparator by which the list is sorted
--   * @return the index at which the key was found, or -n-1 if it was not
--   *         found, where n is the index of the first value higher than key or
--   *         a.length if there is no such value
--   * @throws ClassCastException if key could not be compared with one of the
--   *         elements of l
--   * @throws NullPointerException if a null element is compared with natural
--   *         ordering (only possible when c is null)
--   * @see #sort(List, Comparator)
-+   * @returns the index at which the key was found, or -n-1 if it was not
-+   *   found, where n is the index of the first value higher than key or
-+   *   a.length if there is no such value.
-+   * @exception ClassCastException if key could not be compared with one of the
-+   *   elements of l
-    */
-   public static int binarySearch(List l, Object key, Comparator c)
-   {
--    int pos = 0;
--    int low = 0;
--    int hi = l.size() - 1;
--
--    // We use a linear search with log(n) comparisons using an iterator
--    // if the list is sequential-access.
--    if (isSequential(l))
--      {
--	ListIterator itr = l.listIterator();
--        int i = 0;
--        while (low <= hi)
--          {
--            pos = (low + hi) >> 1;
--            if (i < pos)
--              for ( ; i != pos; i++, itr.next());
--            else
--              for ( ; i != pos; i--, itr.previous());
--	    final int d = compare(key, itr.next(), c);
--	    if (d == 0)
--              return pos;
--	    else if (d < 0)
--              hi = pos - 1;
--	    else
--              // This gets the insertion point right on the last loop
--              low = ++pos;
--          }
--      }
--    else
-+    if (c == null)
-       {
--	while (low <= hi)
--	  {
--	    pos = (low + hi) >> 1;
--	    final int d = compare(key, l.get(pos), c);
--	    if (d == 0)
--              return pos;
--	    else if (d < 0)
--              hi = pos - 1;
--	    else
--              // This gets the insertion point right on the last loop
--              low = ++pos;
--	  }
-+	throw new NullPointerException();
-       }
--
--    // If we failed to find it, we do the same whichever search we did.
--    return -pos - 1;
-+    return search(l, key, c);
-   }
- 
-   /**
-@@ -605,26 +252,30 @@
-    * source list, the remaining elements are unaffected. This method runs in
-    * linear time.
-    *
--   * @param dest the destination list
--   * @param source the source list
--   * @throws IndexOutOfBoundsException if the destination list is shorter
--   *         than the source list (the destination will be unmodified)
--   * @throws UnsupportedOperationException if dest.listIterator() does not
--   *         support the set operation
-+   * @param dest the destination list.
-+   * @param source the source list.
-+   * @exception IndexOutOfBoundsException if the destination list is shorter
-+   *   than the source list (the elements that can be copied will be, prior to
-+   *   the exception being thrown).
-+   * @exception UnsupportedOperationException if dest.listIterator() does not
-+   *   support the set operation.
-    */
-   public static void copy(List dest, List source)
-   {
--    int pos = source.size();
--    if (dest.size() < pos)
--      throw new IndexOutOfBoundsException("Source does not fit in dest");
--
-     Iterator i1 = source.iterator();
-     ListIterator i2 = dest.listIterator();
- 
--    while (--pos >= 0)
-+    try
-+      {
-+	for (int i = source.size() - 1; i >= 0; --i)
-+	  {
-+	    i2.next();
-+	    i2.set(i1.next());
-+	  }
-+      }
-+    catch (NoSuchElementException x)
-       {
--        i2.next();
--        i2.set(i1.next());
-+	throw new IndexOutOfBoundsException("Source doesn't fit in dest.");      
-       }
-   }
- 
-@@ -633,7 +284,7 @@
-    * with legacy APIs that require an Enumeration as input.
-    *
-    * @param c the Collection to iterate over
--   * @return an Enumeration backed by an Iterator over c
-+   * @returns an Enumeration backed by an Iterator over c
-    */
-   public static Enumeration enumeration(Collection c)
-   {
-@@ -657,8 +308,8 @@
-    *
-    * @param l the list to fill.
-    * @param val the object to vill the list with.
--   * @throws UnsupportedOperationException if l.listIterator() does not
--   *         support the set operation.
-+   * @exception UnsupportedOperationException if l.listIterator() does not
-+   *   support the set operation.
-    */
-   public static void fill(List l, Object val)
-   {
-@@ -671,81 +322,30 @@
-   }
- 
-   /**
--   * Returns the starting index where the specified sublist first occurs
--   * in a larger list, or -1 if there is no matching position. If
--   * <code>target.size() &gt; source.size()</code>, this returns -1,
--   * otherwise this implementation uses brute force, checking for
--   * <code>source.sublist(i, i + target.size()).equals(target)</code>
--   * for all possible i.
--   *
--   * @param source the list to search
--   * @param target the sublist to search for
--   * @return the index where found, or -1
--   * @since 1.4
--   */
--  public static int indexOfSubList(List source, List target)
--  {
--    int ssize = source.size();
--    for (int i = 0, j = target.size(); j <= ssize; i++, j++)
--      if (source.subList(i, j).equals(target))
--        return i;
--    return -1;
--  }
--
--  /**
--   * Returns the starting index where the specified sublist last occurs
--   * in a larger list, or -1 if there is no matching position. If
--   * <code>target.size() &gt; source.size()</code>, this returns -1,
--   * otherwise this implementation uses brute force, checking for
--   * <code>source.sublist(i, i + target.size()).equals(target)</code>
--   * for all possible i.
--   *
--   * @param source the list to search
--   * @param target the sublist to search for
--   * @return the index where found, or -1
--   * @since 1.4
--   */
--  public static int lastIndexOfSubList(List source, List target)
--  {
--    int ssize = source.size();
--    for (int i = ssize - target.size(), j = ssize; i >= 0; i--, j--)
--      if (source.subList(i, j).equals(target))
--        return i;
--    return -1;
--  }
--
--  /**
--   * Returns an array list holding the elements visited by a given
--   * Enumeration. This method exists for interoperability between legacy
--   * APIs and the new Collection API.
--   *
--   * @param e the enumeration to put in a list
--   * @return a list containing the enumeration elements
--   * @see ArrayList
--   * @since 1.4
--   */
--  public static List list(Enumeration e)
--  {
--    List l = new ArrayList();
--    while (e.hasMoreElements())
--      l.add(e.nextElement());
--    return l;
--  }
--
--  /**
-    * Find the maximum element in a Collection, according to the natural
-    * ordering of the elements. This implementation iterates over the
-    * Collection, so it works in linear time.
-    *
-    * @param c the Collection to find the maximum element of
--   * @return the maximum element of c
-+   * @returns the maximum element of c
-    * @exception NoSuchElementException if c is empty
-    * @exception ClassCastException if elements in c are not mutually comparable
-    * @exception NullPointerException if null.compareTo is called
-    */
-   public static Object max(Collection c)
-   {
--    return max(c, null);
-+    Iterator itr = c.iterator();
-+    Comparable max = (Comparable) itr.next();	// throws NoSuchElementException
-+    int csize = c.size();
-+    for (int i = 1; i < csize; i++)
-+      {
-+	Object o = itr.next();
-+	if (max.compareTo(o) < 0)
-+	  {
-+	    max = (Comparable) o;
-+	  }
-+      }
-+    return max;
-   }
- 
-   /**
-@@ -754,23 +354,20 @@
-    * works in linear time.
-    *
-    * @param c the Collection to find the maximum element of
--   * @param order the Comparator to order the elements by, or null for natural
--   *        ordering
--   * @return the maximum element of c
--   * @throws NoSuchElementException if c is empty
--   * @throws ClassCastException if elements in c are not mutually comparable
--   * @throws NullPointerException if null is compared by natural ordering
--   *        (only possible when order is null)
-+   * @param order the Comparator to order the elements by
-+   * @returns the maximum element of c
-+   * @exception NoSuchElementException if c is empty
-+   * @exception ClassCastException if elements in c are not mutually comparable
-    */
-   public static Object max(Collection c, Comparator order)
-   {
-     Iterator itr = c.iterator();
--    Object max = itr.next(); // throws NoSuchElementException
-+    Object max = itr.next();	// throws NoSuchElementException
-     int csize = c.size();
-     for (int i = 1; i < csize; i++)
-       {
- 	Object o = itr.next();
--	if (compare(max, o, order) < 0)
-+	if (order.compare(max, o) < 0)
- 	  max = o;
-       }
-     return max;
-@@ -782,14 +379,23 @@
-    * Collection, so it works in linear time.
-    *
-    * @param c the Collection to find the minimum element of
--   * @return the minimum element of c
--   * @throws NoSuchElementException if c is empty
--   * @throws ClassCastException if elements in c are not mutually comparable
--   * @throws NullPointerException if null.compareTo is called
-+   * @returns the minimum element of c
-+   * @exception NoSuchElementException if c is empty
-+   * @exception ClassCastException if elements in c are not mutually comparable
-+   * @exception NullPointerException if null.compareTo is called
-    */
-   public static Object min(Collection c)
-   {
--    return min(c, null);
-+    Iterator itr = c.iterator();
-+    Comparable min = (Comparable) itr.next();	// throws NoSuchElementException
-+    int csize = c.size();
-+    for (int i = 1; i < csize; i++)
-+      {
-+	Object o = itr.next();
-+	if (min.compareTo(o) > 0)
-+	  min = (Comparable) o;
-+      }
-+    return min;
-   }
- 
-   /**
-@@ -798,13 +404,10 @@
-    * works in linear time.
-    *
-    * @param c the Collection to find the minimum element of
--   * @param order the Comparator to order the elements by, or null for natural
--   *        ordering
--   * @return the minimum element of c
--   * @throws NoSuchElementException if c is empty
--   * @throws ClassCastException if elements in c are not mutually comparable
--   * @throws NullPointerException if null is compared by natural ordering
--   *        (only possible when order is null)
-+   * @param order the Comparator to order the elements by
-+   * @returns the minimum element of c
-+   * @exception NoSuchElementException if c is empty
-+   * @exception ClassCastException if elements in c are not mutually comparable
-    */
-   public static Object min(Collection c, Comparator order)
-   {
-@@ -814,7 +417,7 @@
-     for (int i = 1; i < csize; i++)
-       {
- 	Object o = itr.next();
--	if (compare(min, o, order) > 0)
-+	if (order.compare(min, o) > 0)
- 	  min = o;
-       }
-     return min;
-@@ -823,182 +426,54 @@
-   /**
-    * Creates an immutable list consisting of the same object repeated n times.
-    * The returned object is tiny, consisting of only a single reference to the
--   * object and a count of the number of elements. It is Serializable, and
--   * implements RandomAccess. You can use it in tandem with List.addAll for
--   * fast list construction.
-+   * object and a count of the number of elements. It is Serializable.
-    *
-    * @param n the number of times to repeat the object
-    * @param o the object to repeat
--   * @return a List consisting of n copies of o
--   * @throws IllegalArgumentException if n &lt; 0
--   * @see List#addAll(Collection)
--   * @see Serializable
--   * @see RandomAccess
-+   * @returns a List consisting of n copies of o
-+   * @throws IllegalArgumentException if n < 0
-    */
-+  // It's not Serializable, because the serialized form is unspecced.
-+  // Also I'm only assuming that it should be because I don't think it's
-+  // stated - I just would be amazed if it isn't...
-   public static List nCopies(final int n, final Object o)
-   {
--    return new CopiesList(n, o);
--  }
--
--  /**
--   * The implementation of {@link #nCopies(int, Object)}. This class name
--   * is required for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static final class CopiesList extends AbstractList
--    implements Serializable, RandomAccess
--  {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = 2739099268398711800L;
--
--    /**
--     * The count of elements in this list.
--     * @serial the list size
--     */
--    private final int n;
--
--    /**
--     * The repeated list element.
--     * @serial the list contents
--     */
--    private final Object element;
--
--    /**
--     * Constructs the list.
--     *
--     * @param n the count
--     * @param o the object
--     * @throws IllegalArgumentException if n &lt; 0
--     */
--    CopiesList(int n, Object o)
--    {
--      if (n < 0)
-+    // Check for insane arguments
-+    if (n < 0)
-+      {
- 	throw new IllegalArgumentException();
--      this.n = n;
--      element = o;
--    }
--
--    /**
--     * The size is fixed.
--     */
--    public int size()
--    {
--      return n;
--    }
--
--    /**
--     * The same element is returned.
--     */
--    public Object get(int index)
--    {
--      if (index < 0 || index >= n)
--        throw new IndexOutOfBoundsException();
--      return element;
--    }
--
--    // The remaining methods are optional, but provide a performance
--    // advantage by not allocating unnecessary iterators in AbstractList.
--    /**
--     * This list only contains one element.
--     */
--    public boolean contains(Object o)
--    {
--      return n > 0 && equals(o, element);
--    }
--
--    /**
--     * The index is either 0 or -1.
--     */
--    public int indexOf(Object o)
--    {
--      return (n > 0 && equals(o, element)) ? 0 : -1;
--    }
--
--    /**
--     * The index is either n-1 or -1.
--     */
--    public int lastIndexOf(Object o)
--    {
--      return equals(o, element) ? n - 1 : -1;
--    }
--
--    /**
--     * A subList is just another CopiesList.
--     */
--    public List subList(int from, int to)
--    {
--      if (from < 0 || to > n)
--        throw new IndexOutOfBoundsException();
--      return new CopiesList(to - from, element);
--    }
--
--    /**
--     * The array is easy.
--     */
--    public Object[] toArray()
--    {
--      Object[] a = new Object[n];
--      Arrays.fill(a, element);
--      return a;
--    }
-+      }
- 
--    /**
--     * The string is easy to generate.
--     */
--    public String toString()
-+    // Create a minimal implementation of List
-+    return new AbstractList()
-     {
--      StringBuffer r = new StringBuffer("{");
--      for (int i = n - 1; --i > 0; )
--        r.append(element).append(", ");
--      r.append(element).append("}");
--      return r.toString();
--    }
--  } // class CopiesList
-+      public int size()
-+      {
-+	return n;
-+      }
- 
--  /**
--   * Replace all instances of one object with another in the specified list.
--   * The list does not change size. An element e is replaced if
--   * <code>oldval == null ? e == null : oldval.equals(e)</code>.
--   *
--   * @param list the list to iterate over
--   * @param oldval the element to replace
--   * @param newval the new value for the element
--   * @return true if a replacement occurred
--   * @throws UnsupportedOperationException if the list iterator does not allow
--   *         for the set operation
--   * @throws ClassCastException newval is of a type which cannot be added
--   *         to the list
--   * @throws IllegalArgumentException some other aspect of newval stops
--   *         it being added to the list
--   * @since 1.4
--   */
--  public static boolean replaceAll(List list, Object oldval, Object newval)
--  {
--    ListIterator itr = list.listIterator();
--    boolean replace_occured = false;
--    for (int i = list.size(); --i >= 0; )
--      if (AbstractCollection.equals(oldval, itr.next()))
--        {
--          itr.set(newval);
--          replace_occured = true;
--        }
--    return replace_occured;
-+      public Object get(int index)
-+      {
-+	if (index < 0 || index >= n)
-+	  {
-+	    throw new IndexOutOfBoundsException();
-+	  }
-+	return o;
-+      }
-+    };
+@@ -1713,7 +1489,6 @@
+     l.set(i, l.set(j, l.get(i)));
    }
  
+-
    /**
-    * Reverse a given list. This method works in linear time.
-    *
--   * @param l the list to reverse
--   * @throws UnsupportedOperationException if l.listIterator() does not
--   *         support the set operation
-+   * @param l the list to reverse.
-+   * @exception UnsupportedOperationException if l.listIterator() does not
-+   *   support the set operation.
-    */
-   public static void reverse(List l)
-   {
-     ListIterator i1 = l.listIterator();
--    int pos1 = 1;
-+    int pos1 = 0;
-     int pos2 = l.size();
-     ListIterator i2 = l.listIterator(pos2);
-     while (pos1 < pos2)
-@@ -1011,152 +486,42 @@
-       }
-   }
- 
--  /**
--   * Get a comparator that implements the reverse of natural ordering. In
--   * other words, this sorts Comparable objects opposite of how their
--   * compareTo method would sort. This makes it easy to sort into reverse
--   * order, by simply passing Collections.reverseOrder() to the sort method.
--   * The return value of this method is Serializable.
--   *
--   * @return a comparator that imposes reverse natural ordering
--   * @see Comparable
--   * @see Serializable
--   */
--  public static Comparator reverseOrder()
--  {
--    return rcInstance;
--  }
--
--  /**
--   * The object for {@link #reverseOrder()}.
--   */
--  static private final ReverseComparator rcInstance = new ReverseComparator();
--
--  /**
--   * The implementation of {@link #reverseOrder()}. This class name
--   * is required for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static final class ReverseComparator
--    implements Comparator, Serializable
-+  static class ReverseComparator implements Comparator, Serializable
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    static private final long serialVersionUID = 7207038068494060240L;
--
--    /**
--     * A private constructor adds overhead.
--     */
--    ReverseComparator()
--    {
--    }
--
--    /**
--     * Compare two objects in reverse natural order.
--     *
--     * @param a the first object
--     * @param b the second object
--     * @return &lt;, ==, or &gt; 0 according to b.compareTo(a)
--     */
-     public int compare(Object a, Object b)
-     {
--      return ((Comparable) b).compareTo(a);
-+      return -((Comparable) a).compareTo(b);
+    * Returns a synchronized (thread-safe) collection wrapper backed by the
+    * given collection. Notice that element access through the iterators
+@@ -2896,7 +2671,6 @@
      }
-   }
--
-+  
-+  static ReverseComparator rcInstance = new ReverseComparator();
-+  
-   /**
--   * Rotate the elements in a list by a specified distance. After calling this
--   * method, the element now at index <code>i</code> was formerly at index
--   * <code>(i - distance) mod list.size()</code>. The list size is unchanged.
--   * <p>
--   *
--   * For example, suppose a list contains <code>[t, a, n, k, s]</code>. After
--   * either <code>Collections.rotate(l, 4)</code> or
--   * <code>Collections.rotate(l, -1)</code>, the new contents are
--   * <code>[s, t, a, n, k]</code>. This can be applied to sublists to rotate
--   * just a portion of the list. For example, to move element <code>a</code>
--   * forward two positions in the original example, use
--   * <code>Collections.rotate(l.subList(1, 3+1), -1)</code>, which will
--   * result in <code>[t, n, k, a, s]</code>.
--   * <p>
--   *
--   * If the list is small or implements {@link RandomAccess}, the
--   * implementation exchanges the first element to its destination, then the
--   * displaced element, and so on until a circuit has been completed. The
--   * process is repeated if needed on the second element, and so forth, until
--   * all elements have been swapped.  For large non-random lists, the
--   * implementation breaks the list into two sublists at index
--   * <code>-distance mod size</code>, calls {@link #reverse(List)} on the
--   * pieces, then reverses the overall list.
--   *
--   * @param list the list to rotate
--   * @param distance the distance to rotate by; unrestricted in value
--   * @throws UnsupportedOperationException if the list does not support set
--   * @since 1.4
--   */
--  public static void rotate(List list, int distance)
--  {
--    int size = list.size();
--    distance %= size;
--    if (distance == 0)
--      return;
--    if (distance < 0)
--      distance += size;
--
--    if (isSequential(list))
--      {
--        reverse(list);
--        reverse(list.subList(0, distance));
--        reverse(list.subList(distance, size));
--      }
--    else
--      {
--        // Determine the least common multiple of distance and size, as there
--        // are (distance / LCM) loops to cycle through.
--        int a = size;
--        int lcm = distance;
--        int b = a % lcm;
--        while (b != 0)
--          {
--            a = lcm;
--            lcm = b;
--            b = a % lcm;
--          }
--
--        // Now, make the swaps. We must take the remainder every time through
--        // the inner loop so that we don't overflow i to negative values.
--        while (--lcm >= 0)
--          {
--            Object o = list.get(lcm);
--            for (int i = lcm + distance; i != lcm; i = (i + distance) % size)
--              o = list.set(i, o);
--            list.set(lcm, o);
--          }
--      }
-+   * Get a comparator that implements the reverse of natural ordering. This is
-+   * intended to make it easy to sort into reverse order, by simply passing
-+   * Collections.reverseOrder() to the sort method. The return value of this
-+   * method is Serializable.
-+   */
-+  public static Comparator reverseOrder()
-+  {
-+    return rcInstance;
-   }
- 
-   /**
-    * Shuffle a list according to a default source of randomness. The algorithm
--   * used iterates backwards over the list, swapping each element with an
--   * element randomly selected from the elements in positions less than or
--   * equal to it (using r.nextInt(int)).
--   * <p>
--   *
--   * This algorithm would result in a perfectly fair shuffle (that is, each
--   * element would have an equal chance of ending up in any position) if r were
--   * a perfect source of randomness. In practice the results are merely very
--   * close to perfect.
-+   * used would result in a perfectly fair shuffle (that is, each element would
-+   * have an equal chance of ending up in any position) with a perfect source
-+   * of randomness; in practice the results are merely very close to perfect.
-    * <p>
--   *
--   * This method operates in linear time. To do this on large lists which do
--   * not implement {@link RandomAccess}, a temporary array is used to acheive
--   * this speed, since it would be quadratic access otherwise.
--   *
--   * @param l the list to shuffle
--   * @throws UnsupportedOperationException if l.listIterator() does not
--   *         support the set operation
-+   * This method operates in linear time on a random-access list, but may take
-+   * quadratic time on a sequential-access list.
-+   * Note: this (classpath) implementation will never take quadratic time, but
-+   * it does make a copy of the list. This is in line with the behaviour of the
-+   * sort methods and seems preferable.
-+   *
-+   * @param l the list to shuffle.
-+   * @exception UnsupportedOperationException if l.listIterator() does not
-+   *   support the set operation.
-    */
-   public static void shuffle(List l)
-   {
-@@ -1171,12 +536,11 @@
-     shuffle(l, defaultRandom);
-   }
- 
--  /**
--   * Cache a single Random object for use by shuffle(List). This improves
--   * performance as well as ensuring that sequential calls to shuffle() will
--   * not result in the same shuffle order occurring: the resolution of
--   * System.currentTimeMillis() is not sufficient to guarantee a unique seed.
--   */
-+  /** Cache a single Random object for use by shuffle(List). This improves
-+    * performance as well as ensuring that sequential calls to shuffle() will
-+    * not result in the same shuffle order occurring: the resolution of 
-+    * System.currentTimeMillis() is not sufficient to guarantee a unique seed.
-+    */
-   private static Random defaultRandom = null;
- 
-   /**
-@@ -1185,468 +549,147 @@
-    * element randomly selected from the elements in positions less than or
-    * equal to it (using r.nextInt(int)).
-    * <p>
--   *
-    * This algorithm would result in a perfectly fair shuffle (that is, each
-    * element would have an equal chance of ending up in any position) if r were
-    * a perfect source of randomness. In practise (eg if r = new Random()) the
-    * results are merely very close to perfect.
-    * <p>
--   *
--   * This method operates in linear time. To do this on large lists which do
--   * not implement {@link RandomAccess}, a temporary array is used to acheive
--   * this speed, since it would be quadratic access otherwise.
--   *
--   * @param l the list to shuffle
--   * @param r the source of randomness to use for the shuffle
--   * @throws UnsupportedOperationException if l.listIterator() does not
--   *         support the set operation
-+   * This method operates in linear time on a random-access list, but may take
-+   * quadratic time on a sequential-access list.
-+   * Note: this (classpath) implementation will never take quadratic time, but
-+   * it does make a copy of the list. This is in line with the behaviour of the
-+   * sort methods and seems preferable.
-+   *
-+   * @param l the list to shuffle.
-+   * @param r the source of randomness to use for the shuffle.
-+   * @exception UnsupportedOperationException if l.listIterator() does not
-+   *   support the set operation.
-    */
-   public static void shuffle(List l, Random r)
-   {
-+    Object[] a = l.toArray();	// Dump l into an array
-     int lsize = l.size();
-     ListIterator i = l.listIterator(lsize);
--    boolean sequential = isSequential(l);
--    Object[] a = null; // stores a copy of the list for the sequential case
--
--    if (sequential)
--      a = l.toArray();
- 
--    for (int pos = lsize - 1; pos > 0; --pos)
-+    // Iterate backwards over l
-+    for (int pos = lsize - 1; pos >= 0; --pos)
-       {
- 	// Obtain a random position to swap with. pos + 1 is used so that the
- 	// range of the random number includes the current position.
- 	int swap = r.nextInt(pos + 1);
+   } // class SynchronizedSortedSet
  
--	// Swap the desired element.
--	Object o;
--        if (sequential)
--          {
--            o = a[swap];
--            a[swap] = i.previous();
--          }
--        else
--          o = l.set(swap, i.previous());
-+	// Swap the swapth element of the array with the next element of the
-+	// list.
-+	Object o = a[swap];
-+	a[swap] = a[pos];
-+	a[pos] = o;
- 
-+	// Set the element in the original list accordingly.
-+	i.previous();
- 	i.set(o);
-       }
-   }
- 
 -
    /**
-    * Obtain an immutable Set consisting of a single element. The return value
-    * of this method is Serializable.
-    *
--   * @param o the single element
--   * @return an immutable Set containing only o
--   * @see Serializable
--   */
--  public static Set singleton(Object o)
--  {
--    return new SingletonSet(o);
--  }
--
--  /**
--   * The implementation of {@link #singleton(Object)}. This class name
--   * is required for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
-+   * @param o the single element.
-+   * @return an immutable Set containing only o.
-    */
--  private static final class SingletonSet extends AbstractSet
--    implements Serializable
-+  // It's not serializable because the spec is broken.
-+  public static Set singleton(final Object o)
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = 3193687207550431679L;
--
--
--    /**
--     * The single element; package visible for use in nested class.
--     * @serial the singleton
--     */
--    final Object element;
--
--    /**
--     * Construct a singleton.
--     * @param o the element
--     */
--    SingletonSet(Object o)
--    {
--      element = o;
--    }
--
--    /**
--     * The size: always 1!
--     */
--    public int size()
-+    return new AbstractSet()
-     {
--      return 1;
--    }
--
--    /**
--     * Returns an iterator over the lone element.
--     */
--    public Iterator iterator()
--    {
--      return new Iterator()
-+      public int size()
-       {
--        private boolean hasNext = true;
--
--        public boolean hasNext()
--        {
--          return hasNext;
--        }
--
--        public Object next()
--        {
--          if (hasNext)
--          {
--            hasNext = false;
--            return element;
--          }
--          else
--            throw new NoSuchElementException();
--        }
--
--        public void remove()
--        {
--          throw new UnsupportedOperationException();
--        }
--      };
--    }
--
--    // The remaining methods are optional, but provide a performance
--    // advantage by not allocating unnecessary iterators in AbstractSet.
--    /**
--     * The set only contains one element.
--     */
--    public boolean contains(Object o)
--    {
--      return equals(o, element);
--    }
--
--    /**
--     * This is true if the other collection only contains the element.
--     */
--    public boolean containsAll(Collection c)
--    {
--      Iterator i = c.iterator();
--      int pos = c.size();
--      while (--pos >= 0)
--        if (! equals(i.next(), element))
--          return false;
--      return true;
--    }
-+	return 1;
-+      }
- 
--    /**
--     * The hash is just that of the element.
--     */
--    public int hashCode()
--    {
--      return hashCode(element);
--    }
-+      public Iterator iterator()
-+      {
-+	return new Iterator()
-+	{
-+	  private boolean hasNext = true;
- 
--    /**
--     * Returning an array is simple.
--     */
--    public Object[] toArray()
--    {
--      return new Object[] {element};
--    }
-+	  public boolean hasNext()
-+	  {
-+	    return hasNext;
-+	  }
- 
--    /**
--     * Obvious string.
--     */
--    public String toString()
--    {
--      return "[" + element + "]";
--    }
--  } // class SingletonSet
-+	  public Object next()
-+	  {
-+	    if (hasNext)
-+	      {
-+		hasNext = false;
-+		return o;
-+	      }
-+	    else
-+	      {
-+		throw new NoSuchElementException();
-+	      }
-+	  }
- 
--  /**
--   * Obtain an immutable List consisting of a single element. The return value
--   * of this method is Serializable, and implements RandomAccess.
--   *
--   * @param o the single element
--   * @return an immutable List containing only o
--   * @see Serializable
--   * @see RandomAccess
--   * @since 1.3
--   */
--  public static List singletonList(Object o)
--  {
--    return new SingletonList(o);
-+	  public void remove()
-+	  {
-+	    throw new UnsupportedOperationException();
-+	  }
-+	};
-+      }
-+    };
-   }
- 
-   /**
--   * The implementation of {@link #singletonList(Object)}. This class name
--   * is required for compatibility with Sun's JDK serializability.
-+   * Obtain an immutable List consisting of a single element. The return value
-+   * of this method is Serializable.
-    *
--   * @author Eric Blake <ebb9@email.byu.edu>
-+   * @param o the single element.
-+   * @return an immutable List containing only o.
-    */
--  private static final class SingletonList extends AbstractList
--    implements Serializable, RandomAccess
-+  // It's not serializable because the spec is broken.
-+  public static List singletonList(final Object o)
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = 3093736618740652951L;
--
--    /**
--     * The single element.
--     * @serial the singleton
--     */
--    private final Object element;
--
--    /**
--     * Construct a singleton.
--     * @param o the element
--     */
--    SingletonList(Object o)
--    {
--      element = o;
--    }
--
--    /**
--     * The size: always 1!
--     */
--    public int size()
--    {
--      return 1;
--    }
--
--    /**
--     * Only index 0 is valid.
--     */
--    public Object get(int index)
--    {
--      if (index == 0)
--        return element;
--      throw new IndexOutOfBoundsException();
--    }
--
--    // The remaining methods are optional, but provide a performance
--    // advantage by not allocating unnecessary iterators in AbstractList.
--    /**
--     * The set only contains one element.
--     */
--    public boolean contains(Object o)
--    {
--      return equals(o, element);
--    }
--
--    /**
--     * This is true if the other collection only contains the element.
--     */
--    public boolean containsAll(Collection c)
--    {
--      Iterator i = c.iterator();
--      int pos = c.size();
--      while (--pos >= 0)
--        if (! equals(i.next(), element))
--          return false;
--      return true;
--    }
--
--    /**
--     * Speed up the hashcode computation.
--     */
--    public int hashCode()
--    {
--      return 31 + hashCode(element);
--    }
--
--    /**
--     * Either the list has it or not.
--     */
--    public int indexOf(Object o)
--    {
--      return equals(o, element) ? 0 : -1;
--    }
--
--    /**
--     * Either the list has it or not.
--     */
--    public int lastIndexOf(Object o)
--    {
--      return equals(o, element) ? 0 : -1;
--    }
--
--    /**
--     * Sublists are limited in scope.
--     */
--    public List subList(int from, int to)
--    {
--      if (from == to && (to == 0 || to == 1))
--        return EMPTY_LIST;
--      if (from == 0 && to == 1)
--        return this;
--      if (from > to)
--        throw new IllegalArgumentException();
--      throw new IndexOutOfBoundsException();
--    }
--
--    /**
--     * Returning an array is simple.
--     */
--    public Object[] toArray()
--    {
--      return new Object[] {element};
--    }
--
--    /**
--     * Obvious string.
--     */
--    public String toString()
-+    return new AbstractList()
-     {
--      return "[" + element + "]";
--    }
--  } // class SingletonList
-+      public int size()
-+      {
-+	return 1;
-+      }
- 
--  /**
--   * Obtain an immutable Map consisting of a single key-value pair.
--   * The return value of this method is Serializable.
--   *
--   * @param key the single key
--   * @param value the single value
--   * @return an immutable Map containing only the single key-value pair
--   * @see Serializable
--   * @since 1.3
--   */
--  public static Map singletonMap(Object key, Object value)
--  {
--    return new SingletonMap(key, value);
-+      public Object get(int index)
-+      {
-+	if (index == 0)
-+	  {
-+	    throw new IndexOutOfBoundsException();
-+	  }
-+	else
-+	  {
-+	    return o;
-+	  }
-+      }
-+    };
-   }
- 
-   /**
--   * The implementation of {@link #singletonMap(Object)}. This class name
--   * is required for compatibility with Sun's JDK serializability.
-+   * Obtain an immutable Map consisting of a single key value pair.
-+   * The return value of this method is Serializable.
-    *
--   * @author Eric Blake <ebb9@email.byu.edu>
-+   * @param key the single key.
-+   * @param value the single value.
-+   * @return an immutable Map containing only the single key value pair.
-    */
--  private static final class SingletonMap extends AbstractMap
--    implements Serializable
-+  // It's not serializable because the spec is broken.
-+  public static Map singletonMap(final Object key, final Object value)
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = -6979724477215052911L;
--
--    /**
--     * The single key.
--     * @serial the singleton key
--     */
--    private final Object k;
--
--    /**
--     * The corresponding value.
--     * @serial the singleton value
--     */
--    private final Object v;
--
--    /**
--     * Cache the entry set.
--     */
--    private transient Set entries;
--
--    /**
--     * Construct a singleton.
--     * @param key the key
--     * @param value the value
--     */
--    SingletonMap(Object key, Object value)
--    {
--      k = key;
--      v = value;
--    }
--
--    /**
--     * There is a single immutable entry.
--     */
--    public Set entrySet()
--    {
--      if (entries == null)
--        entries = singleton(new BasicMapEntry(k, v)
--        {
--          public Object setValue(Object o)
--          {
--            throw new UnsupportedOperationException();
--          }
--        });
--      return entries;
--    }
--
--    // The remaining methods are optional, but provide a performance
--    // advantage by not allocating unnecessary iterators in AbstractMap.
--    /**
--     * Single entry.
--     */
--    public boolean containsKey(Object key)
--    {
--      return equals(key, k);
--    }
--
--    /**
--     * Single entry.
--     */
--    public boolean containsValue(Object value)
--    {
--      return equals(value, v);
--    }
--
--    /**
--     * Single entry.
--     */
--    public Object get(Object key)
--    {
--      return equals(key, k) ? v : null;
--    }
--
--    /**
--     * Calculate the hashcode directly.
--     */
--    public int hashCode()
--    {
--      return hashCode(k) ^ hashCode(v);
--    }
--
--    /**
--     * Return the keyset.
--     */
--    public Set keySet()
--    {
--      if (keys == null)
--        keys = singleton(k);
--      return keys;
--    }
--
--    /**
--     * The size: always 1!
--     */
--    public int size()
--    {
--      return 1;
--    }
--
--    /**
--     * Return the values. Technically, a singleton, while more specific than
--     * a general Collection, will work. Besides, that's what the JDK uses!
--     */
--    public Collection values()
--    {
--      if (values == null)
--        values = singleton(v);
--      return values;
--    }
--
--    /**
--     * Obvious string.
--     */
--    public String toString()
-+    return new AbstractMap()
-     {
--      return "{" + k + "=" + v + "}";
--    }
--  } // class SingletonMap
-+      public Set entrySet()
-+      {
-+	return singleton(new BasicMapEntry(key, value));
-+      }
-+    };
-+  }
- 
-   /**
-    * Sort a list according to the natural ordering of its elements. The list
-@@ -1657,14 +700,19 @@
-    * the array.
-    *
-    * @param l the List to sort
--   * @throws ClassCastException if some items are not mutually comparable
--   * @throws UnsupportedOperationException if the List is not modifiable
--   * @throws NullPointerException if some element is null
--   * @see Arrays#sort(Object[])
-+   * @exception ClassCastException if some items are not mutually comparable
-+   * @exception UnsupportedOperationException if the List is not modifiable
-    */
-   public static void sort(List l)
-   {
--    sort(l, null);
-+    Object[] a = l.toArray();
-+    Arrays.sort(a);
-+    ListIterator i = l.listIterator();
-+    for (int pos = 0; pos < a.length; pos++)
-+      {
-+	i.next();
-+	i.set(a[pos]);
-+      }
-   }
- 
-   /**
-@@ -1676,1899 +724,1102 @@
-    * the array.
-    *
-    * @param l the List to sort
--   * @param c the Comparator specifying the ordering for the elements, or
--   *        null for natural ordering
--   * @throws ClassCastException if c will not compare some pair of items
--   * @throws UnsupportedOperationException if the List is not modifiable
--   * @throws NullPointerException if null is compared by natural ordering
--   *        (only possible when c is null)
--   * @see Arrays#sort(Object[], Comparator)
-+   * @param c the Comparator specifying the ordering for the elements
-+   * @exception ClassCastException if c will not compare some pair of items
-+   * @exception UnsupportedOperationException if the List is not modifiable
-    */
-   public static void sort(List l, Comparator c)
-   {
-     Object[] a = l.toArray();
-     Arrays.sort(a, c);
--    ListIterator i = l.listIterator(a.length);
--    for (int pos = a.length; --pos >= 0; )
-+    ListIterator i = l.listIterator();
-+    for (int pos = 0; pos < a.length; pos++)
-       {
--	i.previous();
-+	i.next();
- 	i.set(a[pos]);
-       }
-   }
- 
--  /**
--   * Swaps the elements at the specified positions within the list. Equal
--   * positions have no effect.
--   *
--   * @param l the list to work on
--   * @param i the first index to swap
--   * @param j the second index
--   * @throws UnsupportedOperationException if list.set is not supported
--   * @throws IndexOutOfBoundsException if either i or j is &lt; 0 or &gt;=
--   *         list.size()
--   * @since 1.4
--   */
--  public static void swap(List l, int i, int j)
--  {
--    l.set(i, l.set(j, l.get(i)));
--  }
--
--
--  /**
--   * Returns a synchronized (thread-safe) collection wrapper backed by the
--   * given collection. Notice that element access through the iterators
--   * is thread-safe, but if the collection can be structurally modified
--   * (adding or removing elements) then you should synchronize around the
--   * iteration to avoid non-deterministic behavior:<br>
--   * <pre>
--   * Collection c = Collections.synchronizedCollection(new Collection(...));
--   * ...
--   * synchronized (c)
--   *   {
--   *     Iterator i = c.iterator();
--   *     while (i.hasNext())
--   *       foo(i.next());
--   *   }
--   * </pre><p>
--   *
--   * Since the collection might be a List or a Set, and those have incompatible
--   * equals and hashCode requirements, this relies on Object's implementation
--   * rather than passing those calls on to the wrapped collection. The returned
--   * Collection implements Serializable, but can only be serialized if
--   * the collection it wraps is likewise Serializable.
--   *
--   * @param c the collection to wrap
--   * @return a synchronized view of the collection
--   * @see Serializable
--   */
-+  // All the methods from here on in require doc-comments.
-+
-   public static Collection synchronizedCollection(Collection c)
-   {
-     return new SynchronizedCollection(c);
-   }
-+  public static List synchronizedList(List l)
-+  {
-+    return new SynchronizedList(l);
-+  }
-+  public static Map synchronizedMap(Map m)
-+  {
-+    return new SynchronizedMap(m);
-+  }
-+  public static Set synchronizedSet(Set s)
-+  {
-+    return new SynchronizedSet(s);
-+  }
-+  public static SortedMap synchronizedSortedMap(SortedMap m)
-+  {
-+    return new SynchronizedSortedMap(m);
-+  }
-+  public static SortedSet synchronizedSortedSet(SortedSet s)
-+  {
-+    return new SynchronizedSortedSet(s);
-+  }
-+  public static Collection unmodifiableCollection(Collection c)
-+  {
-+    return new UnmodifiableCollection(c);
-+  }
-+  public static List unmodifiableList(List l)
-+  {
-+    return new UnmodifiableList(l);
-+  }
-+  public static Map unmodifiableMap(Map m)
-+  {
-+    return new UnmodifiableMap(m);
-+  }
-+  public static Set unmodifiableSet(Set s)
-+  {
-+    return new UnmodifiableSet(s);
-+  }
-+  public static SortedMap unmodifiableSortedMap(SortedMap m)
-+  {
-+    return new UnmodifiableSortedMap(m);
-+  }
-+  public static SortedSet unmodifiableSortedSet(SortedSet s)
-+  {
-+    return new UnmodifiableSortedSet(s);
-+  }
- 
--  /**
--   * The implementation of {@link #synchronizedCollection(Collection)}. This
--   * class name is required for compatibility with Sun's JDK serializability.
--   * Package visible, so that collections such as the one for
--   * Hashtable.values() can specify which object to synchronize on.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  static class SynchronizedCollection
--    implements Collection, Serializable
-+  // Sun's spec will need to be checked for the precise names of these
-+  // classes, for serializability's sake. However, from what I understand,
-+  // serialization is broken for these classes anyway.
-+
-+  // Note: although this code is largely uncommented, it is all very
-+  // mechanical and there's nothing really worth commenting.
-+  // When serialization of these classes works, we'll need doc-comments on
-+  // them to document the serialized form.
-+
-+  private static class UnmodifiableIterator implements Iterator
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = 3053995032091335093L;
--
--    /**
--     * The wrapped collection. Package visible for use by subclasses.
--     * @serial the real collection
--     */
--    final Collection c;
--
--    /**
--     * The object to synchronize on.  When an instance is created via public
--     * methods, it will be this; but other uses like SynchronizedMap.values()
--     * must specify another mutex. Package visible for use by subclasses.
--     * @serial the lock
--     */
--    final Object mutex;
--
--    /**
--     * Wrap a given collection.
--     * @param c the collection to wrap
--     * @throws NullPointerException if c is null
--     */
--    SynchronizedCollection(Collection c)
-+    private Iterator i;
-+
-+    public UnmodifiableIterator(Iterator i)
-     {
--      this.c = c;
--      mutex = this;
--      if (c == null)
--        throw new NullPointerException();
-+      this.i = i;
-     }
- 
--    /**
--     * Called only by trusted code to specify the mutex as well as the
--     * collection.
--     * @param sync the mutex
--     * @param c the collection
--     */
--    SynchronizedCollection(Object sync, Collection c)
-+    public Object next()
-     {
--      this.c = c;
--      mutex = sync;
-+      return i.next();
-     }
-+    public boolean hasNext()
-+    {
-+      return i.hasNext();
-+    }
-+    public void remove()
-+    {
-+      throw new UnsupportedOperationException();
-+    }
-+  }
- 
--    public boolean add(Object o)
-+  private static class UnmodifiableListIterator extends UnmodifiableIterator
-+    implements ListIterator
-+  {
-+    // This is stored both here and in the superclass, to avoid excessive
-+    // casting.
-+    private ListIterator li;
-+
-+    public UnmodifiableListIterator(ListIterator li)
-     {
--      synchronized (mutex)
--        {
--          return c.add(o);
--        }
-+      super(li);
-+      this.li = li;
-     }
- 
--    public boolean addAll(Collection col)
-+    public boolean hasPrevious()
-+    {
-+      return li.hasPrevious();
-+    }
-+    public Object previous()
-+    {
-+      return li.previous();
-+    }
-+    public int nextIndex()
-+    {
-+      return li.nextIndex();
-+    }
-+    public int previousIndex()
-+    {
-+      return li.previousIndex();
-+    }
-+    public void add(Object o)
-     {
--      synchronized (mutex)
--        {
--          return c.addAll(col);
--        }
-+      throw new UnsupportedOperationException();
-+    }
-+    public void set(Object o)
-+    {
-+      throw new UnsupportedOperationException();
-     }
-+  }
- 
--    public void clear()
-+  private static class UnmodifiableCollection implements Collection,
-+    Serializable
-+  {
-+    Collection c;
-+
-+    public UnmodifiableCollection(Collection c)
-     {
--      synchronized (mutex)
--        {
--          c.clear();
--        }
-+      this.c = c;
-     }
- 
-+    public boolean add(Object o)
-+    {
-+      throw new UnsupportedOperationException();
-+    }
-+    public boolean addAll(Collection c)
-+    {
-+      throw new UnsupportedOperationException();
-+    }
-+    public void clear()
-+    {
-+      throw new UnsupportedOperationException();
-+    }
-     public boolean contains(Object o)
-     {
--      synchronized (mutex)
--        {
--          return c.contains(o);
--        }
-+      return c.contains(o);
-     }
--
-     public boolean containsAll(Collection c1)
-     {
--      synchronized (mutex)
--        {
--          return c.containsAll(c1);
--        }
-+      return c.containsAll(c1);
-     }
--
-     public boolean isEmpty()
-     {
--      synchronized (mutex)
--        {
--          return c.isEmpty();
--        }
-+      return c.isEmpty();
-     }
--
-     public Iterator iterator()
-     {
--      synchronized (mutex)
--        {
--          return new SynchronizedIterator(mutex, c.iterator());
--        }
-+      return new UnmodifiableIterator(c.iterator());
-     }
--
-     public boolean remove(Object o)
-     {
--      synchronized (mutex)
--        {
--          return c.remove(o);
--        }
-+      throw new UnsupportedOperationException();
-     }
--
--    public boolean removeAll(Collection col)
-+    public boolean removeAll(Collection c)
-     {
--      synchronized (mutex)
--        {
--          return c.removeAll(col);
--        }
-+      throw new UnsupportedOperationException();
-     }
--
--    public boolean retainAll(Collection col)
-+    public boolean retainAll(Collection c)
-     {
--      synchronized (mutex)
--        {
--          return c.retainAll(col);
--        }
-+      throw new UnsupportedOperationException();
-     }
--
-     public int size()
-     {
--      synchronized (mutex)
--        {
--          return c.size();
--        }
-+      return c.size();
-     }
--
-     public Object[] toArray()
-     {
--      synchronized (mutex)
--        {
--          return c.toArray();
--        }
--    }
--
--    public Object[] toArray(Object[] a)
--    {
--      synchronized (mutex)
--        {
--          return c.toArray(a);
--        }
--    }
--
--    public String toString()
--    {
--      synchronized (mutex)
--        {
--          return c.toString();
--        }
--    }
--  } // class SynchronizedCollection
--
--  /**
--   * The implementation of the various iterator methods in the
--   * synchronized classes. These iterators must "sync" on the same object
--   * as the collection they iterate over.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static class SynchronizedIterator implements Iterator
--  {
--    /**
--     * The object to synchronize on. Package visible for use by subclass.
--     */
--    final Object mutex;
--
--    /**
--     * The wrapped iterator.
--     */
--    private final Iterator i;
--
--    /**
--     * Only trusted code creates a wrapper, with the specified sync.
--     * @param sync the mutex
--     * @param i the wrapped iterator
--     */
--    SynchronizedIterator(Object sync, Iterator i)
--    {
--      this.i = i;
--      mutex = sync;
-+      return c.toArray();
-     }
--
--    public Object next()
-+    public Object[] toArray(Object[]a)
-     {
--      synchronized (mutex)
--        {
--          return i.next();
--        }
-+      return c.toArray(a);
-     }
--
--    public boolean hasNext()
-+    public String toString()
-     {
--      synchronized (mutex)
--        {
--          return i.hasNext();
--        }
-+      return c.toString();
-     }
--
--    public void remove()
--    {
--      synchronized (mutex)
--        {
--          i.remove();
--        }
--    }
--  } // class SynchronizedIterator
--
--  /**
--   * Returns a synchronized (thread-safe) list wrapper backed by the
--   * given list. Notice that element access through the iterators
--   * is thread-safe, but if the list can be structurally modified
--   * (adding or removing elements) then you should synchronize around the
--   * iteration to avoid non-deterministic behavior:<br>
--   * <pre>
--   * List l = Collections.synchronizedList(new List(...));
--   * ...
--   * synchronized (l)
--   *   {
--   *     Iterator i = l.iterator();
--   *     while (i.hasNext())
--   *       foo(i.next());
--   *   }
--   * </pre><p>
--   *
--   * The returned List implements Serializable, but can only be serialized if
--   * the list it wraps is likewise Serializable. In addition, if the wrapped
--   * list implements RandomAccess, this does too.
--   *
--   * @param l the list to wrap
--   * @return a synchronized view of the list
--   * @see Serializable
--   * @see RandomAccess
--   */
--  public static List synchronizedList(List l)
--  {
--    if (l instanceof RandomAccess)
--      return new SynchronizedRandomAccessList(l);
--    return new SynchronizedList(l);
-   }
- 
--  /**
--   * The implementation of {@link #synchronizedList(List)} for sequential
--   * lists. This class name is required for compatibility with Sun's JDK
--   * serializability. Package visible, so that lists such as Vector.subList()
--   * can specify which object to synchronize on.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  static class SynchronizedList extends SynchronizedCollection
-+  private static class UnmodifiableList extends UnmodifiableCollection
-     implements List
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = -7754090372962971524L;
--
--    /**
--     * The wrapped list; stored both here and in the superclass to avoid
--     * excessive casting. Package visible for use by subclass.
--     * @serial the wrapped list
--     */
--    final List list;
--
--    /**
--     * Wrap a given list.
--     * @param l the list to wrap
--     * @throws NullPointerException if l is null
--     */
--    SynchronizedList(List l)
--    {
--      super(l);
--      list = l;
--    }
-+    // This is stored both here and in the superclass, to avoid excessive
-+    // casting.
-+    List l;
- 
--    /**
--     * Called only by trusted code to specify the mutex as well as the list.
--     * @param sync the mutex
--     * @param l the list
--     */
--    SynchronizedList(Object sync, List l)
-+    public UnmodifiableList(List l)
-     {
--      super(sync, l);
--      list = l;
-+      super(l);
-+      this.l = l;
-     }
- 
-     public void add(int index, Object o)
-     {
--      synchronized (mutex)
--        {
--          list.add(index, o);
--        }
-+      throw new UnsupportedOperationException();
-     }
--
-     public boolean addAll(int index, Collection c)
-     {
--      synchronized (mutex)
--        {
--          return list.addAll(index, c);
--        }
-+      throw new UnsupportedOperationException();
-     }
--
-     public boolean equals(Object o)
-     {
--      synchronized (mutex)
--        {
--          return list.equals(o);
--        }
-+      return l.equals(o);
-     }
--
-     public Object get(int index)
-     {
--      synchronized (mutex)
--        {
--          return list.get(index);
--        }
-+      return l.get(index);
-     }
--
-     public int hashCode()
-     {
--      synchronized (mutex)
--        {
--          return list.hashCode();
--        }
-+      return l.hashCode();
-     }
--
-     public int indexOf(Object o)
-     {
--      synchronized (mutex)
--        {
--          return list.indexOf(o);
--        }
-+      return l.indexOf(o);
-     }
--
-     public int lastIndexOf(Object o)
-     {
--      synchronized (mutex)
--        {
--          return list.lastIndexOf(o);
--        }
-+      return l.lastIndexOf(o);
-     }
--
-     public ListIterator listIterator()
-     {
--      synchronized (mutex)
--        {
--          return new SynchronizedListIterator(mutex, list.listIterator());
--        }
-+      return new UnmodifiableListIterator(l.listIterator());
-     }
--
-     public ListIterator listIterator(int index)
-     {
--      synchronized (mutex)
--        {
--          return new SynchronizedListIterator(mutex, list.listIterator(index));
--        }
-+      return new UnmodifiableListIterator(l.listIterator(index));
-     }
--
-     public Object remove(int index)
-     {
--      synchronized (mutex)
--        {
--          return list.remove(index);
--        }
-+      throw new UnsupportedOperationException();
-     }
--
-     public Object set(int index, Object o)
-     {
--      synchronized (mutex)
--        {
--          return list.set(index, o);
--        }
-+      throw new UnsupportedOperationException();
-     }
--
-     public List subList(int fromIndex, int toIndex)
-     {
--      synchronized (mutex)
--        {
--          return new SynchronizedList(mutex, list.subList(fromIndex, toIndex));
--        }
-+      return new UnmodifiableList(l.subList(fromIndex, toIndex));
-     }
--  } // class SynchronizedList
-+  }
- 
--  /**
--   * The implementation of {@link #synchronizedList(List)} for random-access
--   * lists. This class name is required for compatibility with Sun's JDK
--   * serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static final class SynchronizedRandomAccessList
--    extends SynchronizedList implements RandomAccess
-+  private static class UnmodifiableSet extends UnmodifiableCollection
-+    implements Set
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = 1530674583602358482L;
--
--    /**
--     * Wrap a given list.
--     * @param l the list to wrap
--     * @throws NullPointerException if l is null
--     */
--    SynchronizedRandomAccessList(List l)
-+    public UnmodifiableSet(Set s)
-     {
--      super(l);
-+      super(s);
-     }
--
--    /**
--     * Called only by trusted code to specify the mutex as well as the
--     * collection.
--     * @param sync the mutex
--     * @param l the list
--     */
--    SynchronizedRandomAccessList(Object sync, List l)
-+    public boolean equals(Object o)
-     {
--      super(sync, l);
-+      return c.equals(o);
-     }
--
--    public List subList(int fromIndex, int toIndex)
-+    public int hashCode()
-     {
--      synchronized (mutex)
--        {
--          return new SynchronizedRandomAccessList(mutex,
--                                                  list.subList(fromIndex,
--                                                               toIndex));
--        }
-+      return c.hashCode();
-     }
--  } // class SynchronizedRandomAccessList
-+  }
- 
--  /**
--   * The implementation of {@link SynchronizedList#listIterator()}. This
--   * iterator must "sync" on the same object as the list it iterates over.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static final class SynchronizedListIterator
--    extends SynchronizedIterator implements ListIterator
-+  private static class UnmodifiableSortedSet extends UnmodifiableSet
-+    implements SortedSet
-   {
--    /**
--     * The wrapped iterator, stored both here and in the superclass to
--     * avoid excessive casting.
--     */
--    private final ListIterator li;
--
--    /**
--     * Only trusted code creates a wrapper, with the specified sync.
--     * @param sync the mutex
--     * @param li the wrapped iterator
--     */
--    SynchronizedListIterator(Object sync, ListIterator li)
-+    // This is stored both here and in the superclass, to avoid excessive
-+    // casting.
-+    private SortedSet ss;
-+
-+    public UnmodifiableSortedSet(SortedSet ss)
-     {
--      super(sync, li);
--      this.li = li;
-+      super(ss);
-+      this.ss = ss;
-     }
- 
--    public void add(Object o)
-+    public Comparator comparator()
-     {
--      synchronized (mutex)
--        {
--          li.add(o);
--        }
-+      return ss.comparator();
-     }
--    public boolean hasPrevious()
-+    public Object first()
-     {
--      synchronized (mutex)
--        {
--          return li.hasPrevious();
--        }
-+      return ss.first();
-     }
--
--    public int nextIndex()
-+    public Object last()
-     {
--      synchronized (mutex)
--        {
--          return li.nextIndex();
--        }
-+      return ss.last();
-     }
--
--    public Object previous()
-+    public SortedSet headSet(Object toElement)
-     {
--      synchronized (mutex)
--        {
--          return li.previous();
--        }
-+      return new UnmodifiableSortedSet(ss.headSet(toElement));
-     }
--
--    public int previousIndex()
-+    public SortedSet tailSet(Object fromElement)
-     {
--      synchronized (mutex)
--        {
--          return li.previousIndex();
--        }
-+      return new UnmodifiableSortedSet(ss.tailSet(fromElement));
-     }
--
--    public void set(Object o)
-+    public SortedSet subSet(Object fromElement, Object toElement)
-     {
--      synchronized (mutex)
--        {
--          li.set(o);
--        }
--    }
--  } // class SynchronizedListIterator
--
--  /**
--   * Returns a synchronized (thread-safe) map wrapper backed by the given
--   * map. Notice that element access through the collection views and their
--   * iterators are thread-safe, but if the map can be structurally modified
--   * (adding or removing elements) then you should synchronize around the
--   * iteration to avoid non-deterministic behavior:<br>
--   * <pre>
--   * Map m = Collections.synchronizedMap(new Map(...));
--   * ...
--   * Set s = m.keySet(); // safe outside a synchronized block
--   * synchronized (m) // synch on m, not s
--   *   {
--   *     Iterator i = s.iterator();
--   *     while (i.hasNext())
--   *       foo(i.next());
--   *   }
--   * </pre><p>
--   *
--   * The returned Map implements Serializable, but can only be serialized if
--   * the map it wraps is likewise Serializable.
--   *
--   * @param m the map to wrap
--   * @return a synchronized view of the map
--   * @see Serializable
--   */
--  public static Map synchronizedMap(Map m)
--  {
--    return new SynchronizedMap(m);
-+      return new UnmodifiableSortedSet(ss.subSet(fromElement, toElement));
-+    }
-   }
- 
--  /**
--   * The implementation of {@link #synchronizedMap(Map)}. This
--   * class name is required for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static class SynchronizedMap implements Map, Serializable
-+  private static class UnmodifiableMap implements Map, Serializable
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = 1978198479659022715L;
--
--    /**
--     * The wrapped map.
--     * @serial the real map
--     */
--    private final Map m;
--
--    /**
--     * The object to synchronize on.  When an instance is created via public
--     * methods, it will be this; but other uses like
--     * SynchronizedSortedMap.subMap() must specify another mutex. Package
--     * visible for use by subclass.
--     * @serial the lock
--     */
--    final Object mutex;
--
--    /**
--     * Cache the entry set.
--     */
--    private transient Set entries;
--
--    /**
--     * Cache the key set.
--     */
--    private transient Set keys;
--
--    /**
--     * Cache the value collection.
--     */
--    private transient Collection values;
--
--    /**
--     * Wrap a given map.
--     * @param m the map to wrap
--     * @throws NullPointerException if m is null
--     */
--    SynchronizedMap(Map m)
--    {
--      this.m = m;
--      mutex = this;
--      if (m == null)
--        throw new NullPointerException();
--    }
-+    Map m;
- 
--    /**
--     * Called only by trusted code to specify the mutex as well as the map.
--     * @param sync the mutex
--     * @param m the map
--     */
--    SynchronizedMap(Object sync, Map m)
-+    public UnmodifiableMap(Map m)
-     {
-       this.m = m;
--      mutex = sync;
-     }
- 
-     public void clear()
-     {
--      synchronized (mutex)
--        {
--          m.clear();
--        }
-+      throw new UnsupportedOperationException();
-     }
--
-     public boolean containsKey(Object key)
-     {
--      synchronized (mutex)
--        {
--          return m.containsKey(key);
--        }
-+      return m.containsKey(key);
-     }
--
-     public boolean containsValue(Object value)
-     {
--      synchronized (mutex)
--        {
--          return m.containsValue(value);
--        }
-+      return m.containsValue(value);
-     }
- 
-     // This is one of the ickiest cases of nesting I've ever seen. It just
--    // means "return a SynchronizedSet, except that the iterator() method
--    // returns an SynchronizedIterator whose next() method returns a
--    // synchronized wrapper around its normal return value".
-+    // means "return an UnmodifiableSet, except that the iterator() method
-+    // returns an UnmodifiableIterator whos next() method returns an
-+    // unmodifiable wrapper around its normal return value".
-     public Set entrySet()
-     {
--      // Define this here to spare some nesting.
--      class SynchronizedMapEntry implements Map.Entry
-+      return new UnmodifiableSet(m.entrySet())
-       {
--        final Map.Entry e;
--        SynchronizedMapEntry(Object o)
--        {
--          e = (Map.Entry) o;
--        }
--        public boolean equals(Object o)
--        {
--          synchronized (mutex)
--            {
--              return e.equals(o);
--            }
--        }
--        public Object getKey()
--        {
--          synchronized (mutex)
--            {
--              return e.getKey();
--            }
--        }
--        public Object getValue()
--        {
--          synchronized (mutex)
--            {
--              return e.getValue();
--            }
--        }
--        public int hashCode()
--        {
--          synchronized (mutex)
--            {
--              return e.hashCode();
--            }
--        }
--        public Object setValue(Object value)
--        {
--          synchronized (mutex)
--            {
--              return e.setValue(value);
--            }
--        }
--        public String toString()
--        {
--          synchronized (mutex)
--            {
--              return e.toString();
--            }
--        }
--      } // class SynchronizedMapEntry
--
--      // Now the actual code.
--      if (entries == null)
--        synchronized (mutex)
--          {
--            entries = new SynchronizedSet(mutex, m.entrySet())
--            {
--              public Iterator iterator()
--              {
--                synchronized (super.mutex)
--                  {
--                    return new SynchronizedIterator(super.mutex, c.iterator())
--                    {
--                      public Object next()
--                      {
--                        synchronized (super.mutex)
--                          {
--                            return new SynchronizedMapEntry(super.next());
--                          }
--                      }
--                    };
--                  }
--              }
--            };
--          }
--      return entries;
-+	public Iterator iterator()
-+	{
-+	  return new UnmodifiableIterator(c.iterator())
-+	  {
-+	    public Object next()
-+	    {
-+	      final Map.Entry e = (Map.Entry) super.next();
-+	      return new Map.Entry()
-+	      {
-+		public Object getKey()
-+		{
-+		  return e.getKey();
-+		}
-+		public Object getValue()
-+		{
-+		  return e.getValue();
-+		}
-+		public Object setValue(Object value)
-+		{
-+		  throw new UnsupportedOperationException();
-+		}
-+		public int hashCode()
-+		{
-+		  return e.hashCode();
-+		}
-+		public boolean equals(Object o)
-+		{
-+		  return e.equals(o);
-+		}
-+	      };
-+	    }
-+	  };
-+	}
-+      };
-     }
--
-     public boolean equals(Object o)
-     {
--      synchronized (mutex)
--        {
--          return m.equals(o);
--        }
-+      return m.equals(o);
-     }
--
-     public Object get(Object key)
-     {
--      synchronized (mutex)
--        {
--          return m.get(key);
--        }
-+      return m.get(key);
-+    }
-+    public Object put(Object key, Object value)
-+    {
-+      throw new UnsupportedOperationException();
-     }
--
-     public int hashCode()
-     {
--      synchronized (mutex)
--        {
--          return m.hashCode();
--        }
-+      return m.hashCode();
-     }
--
-     public boolean isEmpty()
-     {
--      synchronized (mutex)
--        {
--          return m.isEmpty();
--        }
-+      return m.isEmpty();
-     }
--
-     public Set keySet()
-     {
--      if (keys == null)
--        synchronized (mutex)
--          {
--            keys = new SynchronizedSet(mutex, m.keySet());
--          }
--      return keys;
--    }
--
--    public Object put(Object key, Object value)
--    {
--      synchronized (mutex)
--        {
--          return m.put(key, value);
--        }
-+      return new UnmodifiableSet(m.keySet());
-     }
--
--    public void putAll(Map map)
-+    public void putAll(Map m)
-     {
--      synchronized (mutex)
--        {
--          m.putAll(map);
--        }
-+      throw new UnsupportedOperationException();
-     }
--
-     public Object remove(Object o)
-     {
--      synchronized (mutex)
--        {
--          return m.remove(o);
--        }
-+      throw new UnsupportedOperationException();
-     }
--
-     public int size()
-     {
--      synchronized (mutex)
--        {
--          return m.size();
--        }
--    }
--
--    public String toString()
--    {
--      synchronized (mutex)
--        {
--          return m.toString();
--        }
-+      return m.size();
-     }
--
-     public Collection values()
-     {
--      if (values == null)
--        synchronized (mutex)
--          {
--            values = new SynchronizedCollection(mutex, m.values());
--          }
--      return values;
--    }
--  } // class SynchronizedMap
--
--  /**
--   * Returns a synchronized (thread-safe) set wrapper backed by the given
--   * set. Notice that element access through the iterator is thread-safe, but
--   * if the set can be structurally modified (adding or removing elements)
--   * then you should synchronize around the iteration to avoid
--   * non-deterministic behavior:<br>
--   * <pre>
--   * Set s = Collections.synchronizedSet(new Set(...));
--   * ...
--   * synchronized (s)
--   *   {
--   *     Iterator i = s.iterator();
--   *     while (i.hasNext())
--   *       foo(i.next());
--   *   }
--   * </pre><p>
--   *
--   * The returned Set implements Serializable, but can only be serialized if
--   * the set it wraps is likewise Serializable.
--   *
--   * @param s the set to wrap
--   * @return a synchronized view of the set
--   * @see Serializable
--   */
--  public static Set synchronizedSet(Set s)
--  {
--    return new SynchronizedSet(s);
--  }
--
--  /**
--   * The implementation of {@link #synchronizedSet(Set)}. This class
--   * name is required for compatibility with Sun's JDK serializability.
--   * Package visible, so that sets such as Hashtable.keySet()
--   * can specify which object to synchronize on.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  static class SynchronizedSet extends SynchronizedCollection
--    implements Set
--  {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = 487447009682186044L;
--
--    /**
--     * Wrap a given set.
--     * @param s the set to wrap
--     * @throws NullPointerException if s is null
--     */
--    SynchronizedSet(Set s)
--    {
--      super(s);
--    }
--
--    /**
--     * Called only by trusted code to specify the mutex as well as the set.
--     * @param sync the mutex
--     * @param s the set
--     */
--    SynchronizedSet(Object sync, Set s)
--    {
--      super(sync, s);
-+      return new UnmodifiableCollection(m.values());
-     }
--
--    public boolean equals(Object o)
-+    public String toString()
-     {
--      synchronized (mutex)
--        {
--          return c.equals(o);
--        }
-+      return m.toString();
-     }
--
--    public int hashCode()
--    {
--      synchronized (mutex)
--        {
--          return c.hashCode();
--        }
--    }
--  } // class SynchronizedSet
--
--  /**
--   * Returns a synchronized (thread-safe) sorted map wrapper backed by the
--   * given map. Notice that element access through the collection views,
--   * subviews, and their iterators are thread-safe, but if the map can be
--   * structurally modified (adding or removing elements) then you should
--   * synchronize around the iteration to avoid non-deterministic behavior:<br>
--   * <pre>
--   * SortedMap m = Collections.synchronizedSortedMap(new SortedMap(...));
--   * ...
--   * Set s = m.keySet(); // safe outside a synchronized block
--   * SortedMap m2 = m.headMap(foo); // safe outside a synchronized block
--   * Set s2 = m2.keySet(); // safe outside a synchronized block
--   * synchronized (m) // synch on m, not m2, s or s2
--   *   {
--   *     Iterator i = s.iterator();
--   *     while (i.hasNext())
--   *       foo(i.next());
--   *     i = s2.iterator();
--   *     while (i.hasNext())
--   *       bar(i.next());
--   *   }
--   * </pre><p>
--   *
--   * The returned SortedMap implements Serializable, but can only be
--   * serialized if the map it wraps is likewise Serializable.
--   *
--   * @param m the sorted map to wrap
--   * @return a synchronized view of the sorted map
--   * @see Serializable
--   */
--  public static SortedMap synchronizedSortedMap(SortedMap m)
--  {
--    return new SynchronizedSortedMap(m);
-   }
- 
--  /**
--   * The implementation of {@link #synchronizedSortedMap(SortedMap)}. This
--   * class name is required for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static final class SynchronizedSortedMap extends SynchronizedMap
-+  private static class UnmodifiableSortedMap extends UnmodifiableMap
-     implements SortedMap
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = -8798146769416483793L;
--
--    /**
--     * The wrapped map; stored both here and in the superclass to avoid
--     * excessive casting.
--     * @serial the wrapped map
--     */
--    private final SortedMap sm;
--
--    /**
--     * Wrap a given map.
--     * @param sm the map to wrap
--     * @throws NullPointerException if sm is null
--     */
--    SynchronizedSortedMap(SortedMap sm)
--    {
--      super(sm);
--      this.sm = sm;
--    }
-+    // This is stored both here and in the superclass, to avoid excessive
-+    // casting.
-+    private SortedMap sm;
- 
--    /**
--     * Called only by trusted code to specify the mutex as well as the map.
--     * @param sync the mutex
--     * @param sm the map
--     */
--    SynchronizedSortedMap(Object sync, SortedMap sm)
-+    public UnmodifiableSortedMap(SortedMap sm)
-     {
--      super(sync, sm);
-+      super(sm);
-       this.sm = sm;
-     }
- 
-     public Comparator comparator()
-     {
--      synchronized (mutex)
--        {
--          return sm.comparator();
--        }
-+      return sm.comparator();
-     }
--
-     public Object firstKey()
-     {
--      synchronized (mutex)
--        {
--          return sm.firstKey();
--        }
-+      return sm.firstKey();
-+    }
-+    public Object lastKey()
-+    {
-+      return sm.lastKey();
-     }
--
-     public SortedMap headMap(Object toKey)
-     {
--      synchronized (mutex)
--        {
--          return new SynchronizedSortedMap(mutex, sm.headMap(toKey));
--        }
-+      return new UnmodifiableSortedMap(sm.headMap(toKey));
-     }
--
--    public Object lastKey()
-+    public SortedMap tailMap(Object fromKey)
-     {
--      synchronized (mutex)
--        {
--          return sm.lastKey();
--        }
-+      return new UnmodifiableSortedMap(sm.tailMap(fromKey));
-     }
--
-     public SortedMap subMap(Object fromKey, Object toKey)
-     {
--      synchronized (mutex)
--        {
--          return new SynchronizedSortedMap(mutex, sm.subMap(fromKey, toKey));
--        }
-+      return new UnmodifiableSortedMap(sm.subMap(fromKey, toKey));
-     }
--
--    public SortedMap tailMap(Object fromKey)
--    {
--      synchronized (mutex)
--        {
--          return new SynchronizedSortedMap(mutex, sm.tailMap(fromKey));
--        }
--    }
--  } // class SynchronizedSortedMap
--
--  /**
--   * Returns a synchronized (thread-safe) sorted set wrapper backed by the
--   * given set. Notice that element access through the iterator and through
--   * subviews are thread-safe, but if the set can be structurally modified
--   * (adding or removing elements) then you should synchronize around the
--   * iteration to avoid non-deterministic behavior:<br>
--   * <pre>
--   * SortedSet s = Collections.synchronizedSortedSet(new SortedSet(...));
--   * ...
--   * SortedSet s2 = s.headSet(foo); // safe outside a synchronized block
--   * synchronized (s) // synch on s, not s2
--   *   {
--   *     Iterator i = s2.iterator();
--   *     while (i.hasNext())
--   *       foo(i.next());
--   *   }
--   * </pre><p>
--   *
--   * The returned SortedSet implements Serializable, but can only be
--   * serialized if the set it wraps is likewise Serializable.
--   *
--   * @param s the sorted set to wrap
--   * @return a synchronized view of the sorted set
--   * @see Serializable
--   */
--  public static SortedSet synchronizedSortedSet(SortedSet s)
--  {
--    return new SynchronizedSortedSet(s);
-   }
- 
--  /**
--   * The implementation of {@link #synchronizedSortedSet(SortedSet)}. This
--   * class name is required for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static final class SynchronizedSortedSet extends SynchronizedSet
--    implements SortedSet
-+  // All the "Synchronized" wrapper objects include a "sync" field which
-+  // specifies what object to synchronize on. That way, nested wrappers such as
-+  // UnmodifiableMap.keySet synchronize on the right things.
-+
-+  private static class SynchronizedIterator implements Iterator
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = 8695801310862127406L;
--
--    /**
--     * The wrapped set; stored both here and in the superclass to avoid
--     * excessive casting.
--     * @serial the wrapped set
--     */
--    private final SortedSet ss;
--
--    /**
--     * Wrap a given set.
--     * @param ss the set to wrap
--     * @throws NullPointerException if ss is null
--     */
--    SynchronizedSortedSet(SortedSet ss)
-+    Object sync;
-+    private Iterator i;
-+
-+    public SynchronizedIterator(Object sync, Iterator i)
-     {
--      super(ss);
--      this.ss = ss;
-+      this.sync = sync;
-+      this.i = i;
-     }
- 
--    /**
--     * Called only by trusted code to specify the mutex as well as the set.
--     * @param sync the mutex
--     * @param l the list
--     */
--    SynchronizedSortedSet(Object sync, SortedSet ss)
-+    public Object next()
-     {
--      super(sync, ss);
--      this.ss = ss;
-+      synchronized(sync)
-+      {
-+	return i.next();
-+      }
-     }
--
--    public Comparator comparator()
-+    public boolean hasNext()
-     {
--      synchronized (mutex)
--        {
--          return ss.comparator();
--        }
-+      synchronized(sync)
-+      {
-+	return i.hasNext();
-+      }
-     }
--
--    public Object first()
-+    public void remove()
-     {
--      synchronized (mutex)
--        {
--          return ss.first();
--        }
-+      synchronized(sync)
-+      {
-+	i.remove();
-+      }
-     }
-+  }
- 
--    public SortedSet headSet(Object toElement)
-+  private static class SynchronizedListIterator extends SynchronizedIterator
-+    implements ListIterator
-+  {
-+    // This is stored both here and in the superclass, to avoid excessive
-+    // casting.
-+    private ListIterator li;
-+
-+    public SynchronizedListIterator(Object sync, ListIterator li)
-     {
--      synchronized (mutex)
--        {
--          return new SynchronizedSortedSet(mutex, ss.headSet(toElement));
--        }
-+      super(sync, li);
-+      this.li = li;
-     }
- 
--    public Object last()
-+    public boolean hasPrevious()
-     {
--      synchronized (mutex)
--        {
--          return ss.last();
--        }
-+      synchronized(sync)
-+      {
-+	return li.hasPrevious();
-+      }
-     }
--
--    public SortedSet subSet(Object fromElement, Object toElement)
-+    public Object previous()
-     {
--      synchronized (mutex)
--        {
--          return new SynchronizedSortedSet(mutex,
--                                           ss.subSet(fromElement, toElement));
--        }
-+      synchronized(sync)
-+      {
-+	return li.previous();
-+      }
-     }
--
--    public SortedSet tailSet(Object fromElement)
-+    public int nextIndex()
-     {
--      synchronized (mutex)
--        {
--          return new SynchronizedSortedSet(mutex, ss.tailSet(fromElement));
--        }
--    }
--  } // class SynchronizedSortedSet
--
--
--  /**
--   * Returns an unmodifiable view of the given collection. This allows
--   * "read-only" access, although changes in the backing collection show up
--   * in this view. Attempts to modify the collection directly or via iterators
--   * will fail with {@link UnsupportedOperationException}.
--   * <p>
--   *
--   * Since the collection might be a List or a Set, and those have incompatible
--   * equals and hashCode requirements, this relies on Object's implementation
--   * rather than passing those calls on to the wrapped collection. The returned
--   * Collection implements Serializable, but can only be serialized if
--   * the collection it wraps is likewise Serializable.
--   *
--   * @param c the collection to wrap
--   * @return a read-only view of the collection
--   * @see Serializable
--   */
--  public static Collection unmodifiableCollection(Collection c)
--  {
--    return new UnmodifiableCollection(c);
-+      synchronized(sync)
-+      {
-+	return li.nextIndex();
-+      }
-+    }
-+    public int previousIndex()
-+    {
-+      synchronized(sync)
-+      {
-+	return li.previousIndex();
-+      }
-+    }
-+    public void add(Object o)
-+    {
-+      synchronized(sync)
-+      {
-+	li.add(o);
-+      }
-+    }
-+    public void set(Object o)
-+    {
-+      synchronized(sync)
-+      {
-+	li.set(o);
-+      }
-+    }
-   }
- 
-   /**
--   * The implementation of {@link #unmodifiableCollection(Collection)}. This
--   * class name is required for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
-+   * Package visible, so that collections such as the one for
-+   * Hashtable.values() can specify which object to synchronize on.
-    */
--  private static class UnmodifiableCollection
--    implements Collection, Serializable
-+  static class SynchronizedCollection implements Collection,
-+    Serializable
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = 1820017752578914078L;
--
--    /**
--     * The wrapped collection. Package visible for use by subclasses.
--     * @serial the real collection
--     */
--    final Collection c;
--
--    /**
--     * Wrap a given collection.
--     * @param c the collection to wrap
--     * @throws NullPointerException if c is null
--     */
--    UnmodifiableCollection(Collection c)
-+    Object sync;
-+    Collection c;
-+
-+    public SynchronizedCollection(Collection c)
-     {
-+      this.sync = this;
-       this.c = c;
--      if (c == null)
--        throw new NullPointerException();
-+    }
-+    public SynchronizedCollection(Object sync, Collection c)
-+    {
-+      this.c = c;
-+      this.sync = sync;
-     }
- 
-     public boolean add(Object o)
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	return c.add(o);
-+      }
-     }
--
--    public boolean addAll(Collection c)
-+    public boolean addAll(Collection col)
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	return c.addAll(col);
-+      }
-     }
--
-     public void clear()
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	c.clear();
-+      }
-     }
--
-     public boolean contains(Object o)
-     {
--      return c.contains(o);
-+      synchronized(sync)
-+      {
-+	return c.contains(o);
-+      }
-     }
--
-     public boolean containsAll(Collection c1)
-     {
--      return c.containsAll(c1);
-+      synchronized(sync)
-+      {
-+	return c.containsAll(c1);
-+      }
-     }
--
-     public boolean isEmpty()
-     {
--      return c.isEmpty();
-+      synchronized(sync)
-+      {
-+	return c.isEmpty();
-+      }
-     }
--
-     public Iterator iterator()
-     {
--      return new UnmodifiableIterator(c.iterator());
-+      synchronized(sync)
-+      {
-+	return new SynchronizedIterator(sync, c.iterator());
-+      }
-     }
--
-     public boolean remove(Object o)
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	return c.remove(o);
-+      }
-     }
--
--    public boolean removeAll(Collection c)
-+    public boolean removeAll(Collection col)
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	return c.removeAll(col);
-+      }
-     }
--
--    public boolean retainAll(Collection c)
-+    public boolean retainAll(Collection col)
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	return c.retainAll(col);
-+      }
-     }
--
-     public int size()
-     {
--      return c.size();
-+      synchronized(sync)
-+      {
-+	return c.size();
-+      }
-     }
--
-     public Object[] toArray()
-     {
--      return c.toArray();
-+      synchronized(sync)
-+      {
-+	return c.toArray();
-+      }
-     }
--
--    public Object[] toArray(Object[] a)
-+    public Object[] toArray(Object[]a)
-     {
--      return c.toArray(a);
-+      synchronized(sync)
-+      {
-+	return c.toArray(a);
-+      }
-     }
--
-     public String toString()
-     {
--      return c.toString();
-+      synchronized(sync)
-+      {
-+	return c.toString();
-+      }
-     }
--  } // class UnmodifiableCollection
-+  }
- 
--  /**
--   * The implementation of the various iterator methods in the
--   * unmodifiable classes.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static class UnmodifiableIterator implements Iterator
-+  private static class SynchronizedList extends SynchronizedCollection
-+    implements List
-   {
--    /**
--     * The wrapped iterator.
--     */
--    private final Iterator i;
--
--    /**
--     * Only trusted code creates a wrapper.
--     * @param i the wrapped iterator
--     */
--    UnmodifiableIterator(Iterator i)
--    {
--      this.i = i;
--    }
--
--    public Object next()
--    {
--      return i.next();
--    }
-+    // This is stored both here and in the superclass, to avoid excessive
-+    // casting.
-+    List l;
- 
--    public boolean hasNext()
-+    public SynchronizedList(Object sync, List l)
-     {
--      return i.hasNext();
-+      super(sync, l);
-+      this.l = l;
-     }
--
--    public void remove()
--    {
--      throw new UnsupportedOperationException();
--    }
--  } // class UnmodifiableIterator
--
--  /**
--   * Returns an unmodifiable view of the given list. This allows
--   * "read-only" access, although changes in the backing list show up
--   * in this view. Attempts to modify the list directly, via iterators, or
--   * via sublists, will fail with {@link UnsupportedOperationException}.
--   * <p>
--   *
--   * The returned List implements Serializable, but can only be serialized if
--   * the list it wraps is likewise Serializable. In addition, if the wrapped
--   * list implements RandomAccess, this does too.
--   *
--   * @param l the list to wrap
--   * @return a read-only view of the list
--   * @see Serializable
--   * @see RandomAccess
--   */
--  public static List unmodifiableList(List l)
--  {
--    if (l instanceof RandomAccess)
--      return new UnmodifiableRandomAccessList(l);
--    return new UnmodifiableList(l);
--  }
--
--  /**
--   * The implementation of {@link #unmodifiableList(List)} for sequential
--   * lists. This class name is required for compatibility with Sun's JDK
--   * serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static class UnmodifiableList extends UnmodifiableCollection
--    implements List
--  {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = -283967356065247728L;
--
--
--    /**
--     * The wrapped list; stored both here and in the superclass to avoid
--     * excessive casting. Package visible for use by subclass.
--     * @serial the wrapped list
--     */
--    final List list;
--
--    /**
--     * Wrap a given list.
--     * @param l the list to wrap
--     * @throws NullPointerException if l is null
--     */
--    UnmodifiableList(List l)
-+    public SynchronizedList(List l)
-     {
-       super(l);
--      list = l;
-+      this.l = l;
-     }
- 
-     public void add(int index, Object o)
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	l.add(index, o);
-+      }
-     }
--
-     public boolean addAll(int index, Collection c)
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	return l.addAll(index, c);
-+      }
-     }
--
-     public boolean equals(Object o)
-     {
--      return list.equals(o);
-+      synchronized(sync)
-+      {
-+	return l.equals(o);
-+      }
-     }
--
-     public Object get(int index)
-     {
--      return list.get(index);
-+      synchronized(sync)
-+      {
-+	return l.get(index);
-+      }
-     }
--
-     public int hashCode()
-     {
--      return list.hashCode();
-+      synchronized(sync)
-+      {
-+	return l.hashCode();
-+      }
-     }
--
-     public int indexOf(Object o)
-     {
--      return list.indexOf(o);
-+      synchronized(sync)
-+      {
-+	return l.indexOf(o);
-+      }
-     }
--
-     public int lastIndexOf(Object o)
-     {
--      return list.lastIndexOf(o);
-+      synchronized(sync)
-+      {
-+	return l.lastIndexOf(o);
-+      }
-     }
--
-     public ListIterator listIterator()
-     {
--      return new UnmodifiableListIterator(list.listIterator());
-+      synchronized(sync)
-+      {
-+	return new SynchronizedListIterator(sync, l.listIterator());
-+      }
-     }
--
-     public ListIterator listIterator(int index)
-     {
--      return new UnmodifiableListIterator(list.listIterator(index));
-+      synchronized(sync)
-+      {
-+	return new SynchronizedListIterator(sync, l.listIterator(index));
-+      }
-     }
--
-     public Object remove(int index)
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	return l.remove(index);
-+      }
-+    }
-+    public boolean remove(Object o)
-+    {
-+      synchronized(sync)
-+      {
-+	return l.remove(o);
-+      }
-     }
--
-     public Object set(int index, Object o)
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	return l.set(index, o);
-+      }
-     }
--
-     public List subList(int fromIndex, int toIndex)
-     {
--      return unmodifiableList(list.subList(fromIndex, toIndex));
-+      synchronized(sync)
-+      {
-+	return new SynchronizedList(l.subList(fromIndex, toIndex));
-+      }
-     }
--  } // class UnmodifiableList
-+  }
- 
-   /**
--   * The implementation of {@link #unmodifiableList(List)} for random-access
--   * lists. This class name is required for compatibility with Sun's JDK
--   * serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
-+   * Package visible, so that sets such as the one for Hashtable.keySet()
-+   * can specify which object to synchronize on.
-    */
--  private static final class UnmodifiableRandomAccessList
--    extends UnmodifiableList implements RandomAccess
-+  static class SynchronizedSet extends SynchronizedCollection
-+    implements Set
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = -2542308836966382001L;
--
--    /**
--     * Wrap a given list.
--     * @param l the list to wrap
--     * @throws NullPointerException if l is null
--     */
--    UnmodifiableRandomAccessList(List l)
-+    public SynchronizedSet(Object sync, Set s)
-     {
--      super(l);
-+      super(sync, s);
-     }
--  } // class UnmodifiableRandomAccessList
--
--  /**
--   * The implementation of {@link UnmodifiableList#listIterator()}.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static final class UnmodifiableListIterator
--    extends UnmodifiableIterator implements ListIterator
--  {
--    /**
--     * The wrapped iterator, stored both here and in the superclass to
--     * avoid excessive casting.
--     */
--    private final ListIterator li;
--
--    /**
--     * Only trusted code creates a wrapper.
--     * @param li the wrapped iterator
--     */
--    UnmodifiableListIterator(ListIterator li)
-+    public SynchronizedSet(Set s)
-     {
--      super(li);
--      this.li = li;
-+      super(s);
-     }
- 
--    public void add(Object o)
-+    public boolean equals(Object o)
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	return c.equals(o);
-+      }
-     }
--
--    public boolean hasPrevious()
-+    public int hashCode()
-     {
--      return li.hasPrevious();
-+      synchronized(sync)
-+      {
-+	return c.hashCode();
-+      }
-     }
-+  }
- 
--    public int nextIndex()
-+  private static class SynchronizedSortedSet extends SynchronizedSet
-+    implements SortedSet
-+  {
-+    // This is stored both here and in the superclass, to avoid excessive
-+    // casting.
-+    private SortedSet ss;
-+
-+    public SynchronizedSortedSet(Object sync, SortedSet ss)
-     {
--      return li.nextIndex();
-+      super(sync, ss);
-+      this.ss = ss;
-     }
--
--    public Object previous()
-+    public SynchronizedSortedSet(SortedSet ss)
-     {
--      return li.previous();
-+      super(ss);
-+      this.ss = ss;
-     }
- 
--    public int previousIndex()
-+    public Comparator comparator()
-     {
--      return li.previousIndex();
-+      synchronized(sync)
-+      {
-+	return ss.comparator();
-+      }
-     }
--
--    public void set(Object o)
-+    public Object first()
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	return ss.first();
-+      }
-+    }
-+    public Object last()
-+    {
-+      synchronized(sync)
-+      {
-+	return ss.last();
-+      }
-+    }
-+    public SortedSet headSet(Object toElement)
-+    {
-+      synchronized(sync)
-+      {
-+	return new SynchronizedSortedSet(sync, ss.headSet(toElement));
-+      }
-+    }
-+    public SortedSet tailSet(Object fromElement)
-+    {
-+      synchronized(sync)
-+      {
-+	return new SynchronizedSortedSet(sync, ss.tailSet(fromElement));
-+      }
-+    }
-+    public SortedSet subSet(Object fromElement, Object toElement)
-+    {
-+      synchronized(sync)
-+      {
-+	return new SynchronizedSortedSet(sync,
-+					 ss.subSet(fromElement, toElement));
-+      }
-     }
--  } // class UnmodifiableListIterator
--
--  /**
--   * Returns an unmodifiable view of the given map. This allows "read-only"
--   * access, although changes in the backing map show up in this view.
--   * Attempts to modify the map directly, or via collection views or their
--   * iterators will fail with {@link UnsupportedOperationException}.
--   * <p>
--   *
--   * The returned Map implements Serializable, but can only be serialized if
--   * the map it wraps is likewise Serializable.
--   *
--   * @param m the map to wrap
--   * @return a read-only view of the map
--   * @see Serializable
--   */
--  public static Map unmodifiableMap(Map m)
--  {
--    return new UnmodifiableMap(m);
-   }
- 
--  /**
--   * The implementation of {@link #unmodifiableMap(Map)}. This
--   * class name is required for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static class UnmodifiableMap implements Map, Serializable
-+  private static class SynchronizedMap implements Map, Serializable
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = -1034234728574286014L;
--
--    /**
--     * The wrapped map.
--     * @serial the real map
--     */
--    private final Map m;
--
--    /**
--     * Cache the entry set.
--     */
--    private transient Set entries;
--
--    /**
--     * Cache the key set.
--     */
--    private transient Set keys;
--
--    /**
--     * Cache the value collection.
--     */
--    private transient Collection values;
--
--    /**
--     * Wrap a given map.
--     * @param m the map to wrap
--     * @throws NullPointerException if m is null
--     */
--    UnmodifiableMap(Map m)
-+    Object sync;
-+    Map m;
-+
-+    public SynchronizedMap(Object sync, Map m)
-+    {
-+      this.sync = sync;
-+      this.m = m;
-+    }
-+    public SynchronizedMap(Map m)
-     {
-       this.m = m;
--      if (m == null)
--        throw new NullPointerException();
-+      this.sync = this;
-     }
- 
-     public void clear()
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	m.clear();
-+      }
-     }
--
-     public boolean containsKey(Object key)
-     {
--      return m.containsKey(key);
-+      synchronized(sync)
-+      {
-+	return m.containsKey(key);
-+      }
-     }
--
-     public boolean containsValue(Object value)
-     {
--      return m.containsValue(value);
-+      synchronized(sync)
-+      {
-+	return m.containsValue(value);
-+      }
-     }
- 
-+    // This is one of the ickiest cases of nesting I've ever seen. It just
-+    // means "return a SynchronizedSet, except that the iterator() method
-+    // returns an SynchronizedIterator whos next() method returns a
-+    // synchronized wrapper around its normal return value".
-     public Set entrySet()
-     {
--      if (entries == null)
--        entries = new UnmodifiableEntrySet(m.entrySet());
--      return entries;
--    }
--
--    /**
--     * The implementation of {@link UnmodifiableMap#entrySet()}. This class
--     * name is required for compatibility with Sun's JDK serializability.
--     *
--     * @author Eric Blake <ebb9@email.byu.edu>
--     */
--    private static final class UnmodifiableEntrySet extends UnmodifiableSet
--      implements Serializable
--    {
--      /**
--       * Compatible with JDK 1.4.
--       */
--      private static final long serialVersionUID = 7854390611657943733L;
--
--      /**
--       * Wrap a given set.
--       * @param s the set to wrap
--       */
--      UnmodifiableEntrySet(Set s)
--      {
--        super(s);
--      }
--
--      // The iterator must return unmodifiable map entries.
--      public Iterator iterator()
-+      synchronized(sync)
-       {
--        return new UnmodifiableIterator(c.iterator())
-+	return new SynchronizedSet(sync, m.entrySet())
- 	{
--          public Object next()
--          {
--            final Map.Entry e = (Map.Entry) super.next();
--            return new Map.Entry()
-+	  public Iterator iterator()
-+	  {
-+	    synchronized(SynchronizedMap.this.sync)
- 	    {
--              public boolean equals(Object o)
--              {
--                return e.equals(o);
--              }
--              public Object getKey()
--              {
--                return e.getKey();
--              }
--              public Object getValue()
--              {
--                return e.getValue();
--              }
--              public int hashCode()
--              {
--                return e.hashCode();
--              }
--              public Object setValue(Object value)
--              {
--                throw new UnsupportedOperationException();
--              }
--              public String toString()
--              {
--                return e.toString();
--              }
--	    };
--          }
-+	      return new SynchronizedIterator(SynchronizedMap.this.sync,
-+					      c.iterator())
-+	      {
-+		public Object next()
-+		{
-+		  synchronized(SynchronizedMap.this.sync)
-+		  {
-+		    final Map.Entry e = (Map.Entry) super.next();
-+		    return new Map.Entry()
-+		    {
-+		      public Object getKey()
-+		      {
-+			synchronized(SynchronizedMap.this.sync)
-+			{
-+			  return e.getKey();
-+			}
-+		      }
-+		      public Object getValue()
-+		      {
-+			synchronized(SynchronizedMap.this.sync)
-+			{
-+			  return e.getValue();
-+			}
-+		      }
-+		      public Object setValue(Object value)
-+		      {
-+			synchronized(SynchronizedMap.this.sync)
-+			{
-+			  return e.setValue(value);
-+			}
-+		      }
-+		      public int hashCode()
-+		      {
-+			synchronized(SynchronizedMap.this.sync)
-+			{
-+			  return e.hashCode();
-+			}
-+		      }
-+		      public boolean equals(Object o)
-+		      {
-+			synchronized(SynchronizedMap.this.sync)
-+			{
-+			  return e.equals(o);
-+			}
-+		      }
-+		    };
-+		  }
-+		}
-+	      };
-+	    }
-+	  }
- 	};
-       }
--    } // class UnmodifiableEntrySet
--
-+    }
-     public boolean equals(Object o)
-     {
--      return m.equals(o);
-+      synchronized(sync)
-+      {
-+	return m.equals(o);
-+      }
-     }
--
-     public Object get(Object key)
-     {
--      return m.get(key);
-+      synchronized(sync)
-+      {
-+	return m.get(key);
-+      }
-     }
--
-     public Object put(Object key, Object value)
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	return m.put(key, value);
-+      }
-     }
--
-     public int hashCode()
-     {
--      return m.hashCode();
-+      synchronized(sync)
-+      {
-+	return m.hashCode();
-+      }
-     }
--
-     public boolean isEmpty()
-     {
--      return m.isEmpty();
-+      synchronized(sync)
-+      {
-+	return m.isEmpty();
-+      }
-     }
--
-     public Set keySet()
-     {
--      if (keys == null)
--        keys = new UnmodifiableSet(m.keySet());
--      return keys;
-+      synchronized(sync)
-+      {
-+	return new SynchronizedSet(sync, m.keySet());
-+      }
-     }
--
--    public void putAll(Map m)
-+    public void putAll(Map map)
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	m.putAll(map);
-+      }
-     }
--
-     public Object remove(Object o)
-     {
--      throw new UnsupportedOperationException();
-+      synchronized(sync)
-+      {
-+	return m.remove(o);
-+      }
-     }
- 
-     public int size()
-     {
--      return m.size();
-+      synchronized(sync)
-+      {
-+	return m.size();
-+      }
-     }
--
--    public String toString()
-+    public Collection values()
-     {
--      return m.toString();
-+      synchronized(sync)
-+      {
-+	return new SynchronizedCollection(sync, m.values());
-+      }
-     }
--
--    public Collection values()
-+    public String toString()
-     {
--      if (values == null)
--        values = new UnmodifiableCollection(m.values());
--      return values;
-+      synchronized(sync)
-+      {
-+	return m.toString();
-+      }
-     }
--  } // class UnmodifiableMap
--
--  /**
--   * Returns an unmodifiable view of the given set. This allows
--   * "read-only" access, although changes in the backing set show up
--   * in this view. Attempts to modify the set directly or via iterators
--   * will fail with {@link UnsupportedOperationException}.
--   * <p>
--   *
--   * The returned Set implements Serializable, but can only be serialized if
--   * the set it wraps is likewise Serializable.
--   *
--   * @param s the set to wrap
--   * @return a read-only view of the set
--   * @see Serializable
--   */
--  public static Set unmodifiableSet(Set s)
--  {
--    return new UnmodifiableSet(s);
-   }
- 
--  /**
--   * The implementation of {@link #unmodifiableSet(Set)}. This class
--   * name is required for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static class UnmodifiableSet extends UnmodifiableCollection
--    implements Set
-+  private static class SynchronizedSortedMap extends SynchronizedMap
-+    implements SortedMap
-   {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = -9215047833775013803L;
--
--    /**
--     * Wrap a given set.
--     * @param s the set to wrap
--     * @throws NullPointerException if s is null
--     */
--    UnmodifiableSet(Set s)
--    {
--      super(s);
--    }
-+    // This is stored both here and in the superclass, to avoid excessive
-+    // casting.
-+    private SortedMap sm;
- 
--    public boolean equals(Object o)
-+    public SynchronizedSortedMap(Object sync, SortedMap sm)
-     {
--      return c.equals(o);
-+      super(sync, sm);
-+      this.sm = sm;
-     }
--
--    public int hashCode()
--    {
--      return c.hashCode();
--    }
--  } // class UnmodifiableSet
--
--  /**
--   * Returns an unmodifiable view of the given sorted map. This allows
--   * "read-only" access, although changes in the backing map show up in this
--   * view. Attempts to modify the map directly, via subviews, via collection
--   * views, or iterators, will fail with {@link UnsupportedOperationException}.
--   * <p>
--   *
--   * The returned SortedMap implements Serializable, but can only be
--   * serialized if the map it wraps is likewise Serializable.
--   *
--   * @param m the map to wrap
--   * @return a read-only view of the map
--   * @see Serializable
--   */
--  public static SortedMap unmodifiableSortedMap(SortedMap m)
--  {
--    return new UnmodifiableSortedMap(m);
--  }
--
--  /**
--   * The implementation of {@link #unmodifiableSortedMap(SortedMap)}. This
--   * class name is required for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static class UnmodifiableSortedMap extends UnmodifiableMap
--    implements SortedMap
--  {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = -8806743815996713206L;
--
--    /**
--     * The wrapped map; stored both here and in the superclass to avoid
--     * excessive casting.
--     * @serial the wrapped map
--     */
--    private final SortedMap sm;
--
--    /**
--     * Wrap a given map.
--     * @param sm the map to wrap
--     * @throws NullPointerException if sm is null
--     */
--    UnmodifiableSortedMap(SortedMap sm)
-+    public SynchronizedSortedMap(SortedMap sm)
-     {
-       super(sm);
-       this.sm = sm;
-@@ -3576,114 +1827,36 @@
- 
-     public Comparator comparator()
-     {
--      return sm.comparator();
-+      synchronized(sync)
-+      {
-+	return sm.comparator();
-+      }
-     }
--
-     public Object firstKey()
-     {
--      return sm.firstKey();
--    }
--
--    public SortedMap headMap(Object toKey)
--    {
--      return new UnmodifiableSortedMap(sm.headMap(toKey));
-+      synchronized(sync)
-+      {
-+	return sm.firstKey();
-+      }
-     }
--
-     public Object lastKey()
-     {
--      return sm.lastKey();
-+      synchronized(sync)
-+      {
-+	return sm.lastKey();
-+      }
-     }
--
--    public SortedMap subMap(Object fromKey, Object toKey)
-+    public SortedMap headMap(Object toKey)
-     {
--      return new UnmodifiableSortedMap(sm.subMap(fromKey, toKey));
-+      return new SynchronizedSortedMap(sync, sm.headMap(toKey));
-     }
--
-     public SortedMap tailMap(Object fromKey)
-     {
--      return new UnmodifiableSortedMap(sm.tailMap(fromKey));
--    }
--  } // class UnmodifiableSortedMap
--
--  /**
--   * Returns an unmodifiable view of the given sorted set. This allows
--   * "read-only" access, although changes in the backing set show up
--   * in this view. Attempts to modify the set directly, via subsets, or via
--   * iterators, will fail with {@link UnsupportedOperationException}.
--   * <p>
--   *
--   * The returns SortedSet implements Serializable, but can only be
--   * serialized if the set it wraps is likewise Serializable.
--   *
--   * @param s the set to wrap
--   * @return a read-only view of the set
--   * @see Serializable
--   */
--  public static SortedSet unmodifiableSortedSet(SortedSet s)
--  {
--    return new UnmodifiableSortedSet(s);
--  }
--
--  /**
--   * The implementation of {@link #synchronizedSortedMap(SortedMap)}. This
--   * class name is required for compatibility with Sun's JDK serializability.
--   *
--   * @author Eric Blake <ebb9@email.byu.edu>
--   */
--  private static class UnmodifiableSortedSet extends UnmodifiableSet
--    implements SortedSet
--  {
--    /**
--     * Compatible with JDK 1.4.
--     */
--    private static final long serialVersionUID = -4929149591599911165L;
--
--    /**
--     * The wrapped set; stored both here and in the superclass to avoid
--     * excessive casting.
--     * @serial the wrapped set
--     */
--    private SortedSet ss;
--
--    /**
--     * Wrap a given set.
--     * @param ss the set to wrap
--     * @throws NullPointerException if ss is null
--     */
--    UnmodifiableSortedSet(SortedSet ss)
--    {
--      super(ss);
--      this.ss = ss;
--    }
--
--    public Comparator comparator()
--    {
--      return ss.comparator();
--    }
--
--    public Object first()
--    {
--      return ss.first();
--    }
--
--    public SortedSet headSet(Object toElement)
--    {
--      return new UnmodifiableSortedSet(ss.headSet(toElement));
--    }
--
--    public Object last()
--    {
--      return ss.last();
--    }
--
--    public SortedSet subSet(Object fromElement, Object toElement)
--    {
--      return new UnmodifiableSortedSet(ss.subSet(fromElement, toElement));
-+      return new SynchronizedSortedMap(sync, sm.tailMap(fromKey));
-     }
--
--    public SortedSet tailSet(Object fromElement)
-+    public SortedMap subMap(Object fromKey, Object toKey)
-     {
--      return new UnmodifiableSortedSet(ss.tailSet(fromElement));
-+      return new SynchronizedSortedMap(sync, sm.subMap(fromKey, toKey));
-     }
--  } // class UnmodifiableSortedSet
--} // class Collections
-+  }
-+}
+    * Returns an unmodifiable view of the given collection. This allows
+    * "read-only" access, although changes in the backing collection show up
Index: compare/java.util.List.diff
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/java/compare/java.util.List.diff,v
retrieving revision 1.1
diff -u -r1.1 java.util.List.diff
--- compare/java.util.List.diff 2001/11/07 01:23:49 1.1
+++ compare/java.util.List.diff 2001/12/16 00:14:01
@@ -1,11 +1,11 @@
 --- /home/tromey/gnu/egcs/classpath/classpath/java/util/List.java	Mon Oct 15 10:45:18 2001
-+++ java/util/List.java	Fri Nov  2 21:44:52 2001
-@@ -288,7 +288,7 @@
-   Object remove(int index);
++++ java/util/List.java	Sat Dec 15 09:16:04 2001
+@@ -190,7 +190,7 @@
+    * @see Object#equals(Object)
+    * @see #hashCode()
+    */
+-  boolean equals(Object o);
++ /* boolean equals(Object o);*/
  
    /**
--   * Remove the first occurence of an object from this list (optional
-+   * Remove the first occurrence of an object from this list (optional
-    * operation). That is, remove the first element e such that
-    * <code>o == null ? e == null : o.equals(e)</code>.
-    *
+    * Get the element at a given index in this list.
Index: compare/java.util.TreeMap.diff
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/java/compare/java.util.TreeMap.diff,v
retrieving revision 1.2
diff -u -r1.2 java.util.TreeMap.diff
--- compare/java.util.TreeMap.diff 2001/12/07 23:22:19 1.2
+++ compare/java.util.TreeMap.diff 2001/12/16 00:14:01
@@ -1,2767 +1,9 @@
 --- /home/tromey/gnu/egcs/classpath/classpath/java/util/TreeMap.java	Sun Nov 25 12:30:06 2001
-+++ java/util/TreeMap.java	Tue Oct 16 09:14:35 2001
-@@ -38,166 +38,80 @@
-  * 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.
-+ * The algorithms are adopted from Corman, Leiserson,
-+ * and Rivest's <i>Introduction to Algorithms.</i>  In other words,
-+ * I cribbed from the same pseudocode as Sun.  <em>Any similarity
-+ * between my code and Sun's (if there is any -- I have never looked
-+ * at Sun's) is a result of this fact.</em>
-  *
-- * 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>
-+ * 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.
-  *
-- * 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.
-+ * 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.  Null values are 
-+ * always allowed.
-  *
-- * @author Jon Zeppieri
-- * @author Bryce McKinlay
-- * @author Eric Blake <ebb9@email.byu.edu>
-- * @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.4
-+ * @author           Jon Zeppieri
-+ * @author	     Bryce McKinlay
-  */
- public class TreeMap extends AbstractMap
-   implements SortedMap, 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;
-+  private static final int RED = -1,
-+                           BLACK = 1;
- 
--  /**
--   * 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;
--    }
-+  /** Sentinal node, used to avoid null checks for corner cases and make the
-+      delete rebalance code simpler. Note that this must not be static, due 
-+      to thread-safety concerns. */
-+  transient Node nil = new Node(null, null);
- 
--  /**
--   * The root node of this TreeMap.
--   */
--  private transient Node root = nil;
-+  /** The root node of this TreeMap */
-+  transient Node root = nil;
- 
--  /**
--   * The size of this TreeMap. Package visible for use by nested classes.
--   */
--  transient int size;
-+  /** The size of this TreeMap */
-+  transient int size = 0;
- 
--  /**
--   * The cache for {@link #entrySet()}.
--   */
--  private transient Set entries;
-+  /** Number of modifications */
-+  transient int modCount = 0;
- 
--  /**
--   * 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, if any. */
-+  Comparator comparator = null;
- 
--  /**
--   * 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 comparator;
-+  static final long serialVersionUID = 919286545866124006L;
- 
--  /**
--   * 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 extends BasicMapEntry
-+  private static class Node extends BasicMapEntry implements Map.Entry
-   {
--    // All fields package visible for use by nested classes.
--    /** The color of this node. */
-     int color;
-+    Node left;
-+    Node right;
-+    Node parent;
- 
--    /** The left child node. */
--    Node left = nil;
--    /** The right child node. */
--    Node right = nil;
--    /** The parent node. */
--    Node parent = nil;
--
--    /**
--     * Simple constructor.
--     * @param key the key
--     * @param value the value
--     */
--    Node(Object key, Object value, int color)
-+    Node(Object key, Object value)
-     {
-       super(key, value);
--      this.color = color;
-+      this.color = BLACK;
++++ java/util/TreeMap.java	Sat Dec 15 09:16:04 2001
+@@ -1759,5 +1759,5 @@
+         };
+       return this.keys;
      }
-   }
- 
-   /**
--   * 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}.
-+   * Instantiate a new TreeMap with no elements, using the keys'
-+   * natural ordering to sort.
-    *
--   * @see Comparable
-+   * @see java.lang.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}.
-+   * Instantiate a new TreeMap with no elements, using the provided
-+   * comparator to sort.
-    *
--   * @param comparator the sort order for the keys of this map, or null
--   *        for the natural order
-+   * @param        oComparator        a Comparator object, used to sort 
-+   *                                  the keys of this SortedMap
-    */
-   public TreeMap(Comparator c)
-   {
-@@ -205,70 +119,62 @@
-   }
- 
-   /**
--   * 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}.
-+   * 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.
-+   *
-+   * @param              map         a Map, whose keys will be put into
-+   *                                  this TreeMap
-+   *
-+   * @throws             ClassCastException     if the keys in the provided
-+   *                                            Map do not implement 
-+   *                                            Comparable
-    *
--   * @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
-+   * @see                java.lang.Comparable
-    */
-   public TreeMap(Map 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
-+  /** 
-+   * Instantiate a new TreeMap, initializing it with all of the
-+   * elements in the provided SortedMap.  The elements will be sorted 
-+   * using the same method as in the provided SortedMap.
-    */
-   public TreeMap(SortedMap sm)
-   {
-     this(sm.comparator());
--    int pos = sm.size();
-+
-+    int sm_size = sm.size();
-     Iterator itr = sm.entrySet().iterator();
- 
--    fabricateTree(pos);
-+    fabricateTree(sm_size);
-     Node node = firstNode();
--
--    while (--pos >= 0)
-+    
-+    for (int i = 0; i < sm_size; i++)
-       {
--        Map.Entry me = (Map.Entry) itr.next();
--        node.key = me.getKey();
--        node.value = me.getValue();
--        node = successor(node);
-+	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 int size()
-+  {
-+    return size;
-+  }
-+
-   public void clear()
-   {
--    if (size > 0)
--      {
--        modCount++;
--        root = nil;
--        size = 0;
--      }
-+    modCount++;
-+    root = nil;
-+    // nil node could have a residual parent reference, clear it for GC.
-+    nil.parent = null;
-+    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;
-@@ -279,805 +185,547 @@
-     catch (CloneNotSupportedException x)
-       {
-       }
--    copy.entries = null;
-+    // Each instance must have a unique sentinal.
-+    copy.nil = new Node(null, 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);
-+	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 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(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();
-+    Object currentVal;
-+
-     while (node != nil)
-       {
--        if (equals(value, node.value))
--          return true;
--        node = successor(node);
-+	currentVal = node.getValue();
-+
-+        if (value == null ? currentVal == null : value.equals (currentVal))
-+	  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 entrySet()
-   {
--    if (entries == null)
--      // Create an AbstractSet with custom implementations of those methods
--      // that can be overriden easily and efficiently.
--      entries = new AbstractSet()
-+    // Create an AbstractSet with custom implementations of those methods that 
-+    // can be overriden easily and efficiently.
-+    return new AbstractSet()
-+    {
-+      public int size()
-       {
--        public int size()
--        {
--          return size;
--        }
--
--        public Iterator 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 me = (Map.Entry) o;
--          Node n = getNode(me.getKey());
--          return n != nil && AbstractSet.equals(me.getValue(), n.value);
-+        return size;
-+      }
-+      
-+      public Iterator iterator()
-+      {
-+        return new TreeIterator(TreeIterator.ENTRIES);
-+      }
-+            
-+      public void clear()
-+      {
-+        TreeMap.this.clear();
-       }
- 
--        public boolean remove(Object o)
--        {
--          if (! (o instanceof Map.Entry))
--            return false;
--          Map.Entry me = (Map.Entry) o;
--          Node n = getNode(me.getKey());
--          if (n != nil && AbstractSet.equals(me.getValue(), n.value))
--            {
--              removeNode(n);
--              return true;
--            }
--          return false;
--        }
--      };
--    return entries;
-+      public boolean contains(Object o)
-+      {
-+        if (!(o instanceof Map.Entry))
-+	  return false;
-+	Map.Entry me = (Map.Entry) o;
-+	Node n = getNode(me.getKey());
-+	return (n != nil && me.getValue().equals(n.value));
-+      }
-+      
-+      public boolean remove(Object o)
-+      {
-+        if (!(o instanceof Map.Entry))
-+	  return false;
-+	Map.Entry me = (Map.Entry) o;
-+	Node n = getNode(me.getKey());
-+	if (n != nil && me.getValue().equals(n.value))
-+	  {
-+	    removeNode(n);
-+	    return true;
-+	  }
-+	return false;
-+      }
-+    };
-   }
- 
--  /**
--   * Returns the first (lowest) key in the map.
--   *
--   * @return the first key
--   * @throws NoSuchElementException if the map is empty
--   */
-   public Object firstKey()
-   {
-     if (root == nil)
--      throw new NoSuchElementException();
--    return firstNode().key;
-+      throw new NoSuchElementException("empty");
-+    return firstNode().getKey();
-+  }
-+  
-+  private Node firstNode()
-+  {
-+    if (root == nil)
-+      return nil;
-+    Node node = root;
-+    while (node.left != nil)
-+      node = node.left;
-+    return node;
-   }
- 
--  /**
--   * 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 Object lastKey()
-+  {
-+    if (root == nil)
-+      throw new NoSuchElementException("empty");
-+    return lastNode().getKey();
-+  }
-+  
-+  private Node lastNode()
-+  {
-+    if (root == nil)
-+      return nil;
-+    Node node = root;
-+    while (node.right != nil)
-+      node = node.right;
-+    return node;  
-+  }
-+  
-   public Object get(Object key)
-   {
--    // Exploit fact that nil.value == null.
-     return getNode(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.
--   *
--   * @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 headMap(Object toKey)
-+  
-+  /** Return the TreeMap.Node associated with KEY, or the nil node if no such
-+      node exists in the tree. */
-+  private Node getNode(Object key)
-   {
--    return new SubMap(nil, toKey);
-+    int comparison;
-+    Node current = root;
-+
-+    while (current != nil)
-+      {
-+        comparison = compare(key, current.key);
-+	if (comparison > 0)
-+	  current = current.right;
-+	else if (comparison < 0)
-+	  current = current.left;
-+	else
-+	  return current;
-+      }
-+    return current; 
-   }
- 
--  /**
--   * 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 keySet()
-   {
--    if (keys == null)
--      // Create an AbstractSet with custom implementations of those methods
--      // that can be overriden easily and efficiently.
--      keys = new AbstractSet()
-+    // Create an AbstractSet with custom implementations of those methods that 
-+    // can be overriden easily and efficiently.
-+    return new AbstractSet()
-+    {
-+      public int size()
-       {
--        public int size()
--        {
--          return size;
--        }
--
--        public Iterator iterator()
--        {
--          return new TreeIterator(KEYS);
--        }
--
--        public void clear()
--        {
--          TreeMap.this.clear();
--        }
--
--        public boolean contains(Object o)
--        {
--          return containsKey(o);
--        }
-+        return size;
-+      }
-+      
-+      public Iterator iterator()
-+      {
-+        return new TreeIterator(TreeIterator.KEYS);
-+      }
- 
--        public boolean remove(Object key)
--        {
--          Node n = getNode(key);
--          if (n == nil)
--            return false;
--          removeNode(n);
--          return true;
--        }
--      };
--    return keys;
--  }
-+      public void clear()
-+      {
-+        TreeMap.this.clear();
-+      }
- 
--  /**
--   * Returns the last (highest) key in the map.
--   *
--   * @return the last key
--   * @throws NoSuchElementException if the map is empty
--   */
--  public Object lastKey()
--  {
--    if (root == nil)
--      throw new NoSuchElementException("empty");
--    return lastNode().key;
-+      public boolean contains(Object o)
-+      {
-+        return TreeMap.this.containsKey(o);
-+      }
-+      
-+      public boolean remove(Object key)
-+      {
-+        Node n = getNode(key);
-+	if (n == nil)
-+	  return false;
-+        TreeMap.this.removeNode(n);
-+	return true;
-+      }
-+    };
-   }
- 
--  /**
--   * 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 HashMap
--   * @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 Object put(Object key, Object value)
-   {
-+    modCount++;
-     Node current = root;
-     Node 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);
-+	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.
-+	    Object r = current.value;
-+	    current.value = value;
-+	    return r;
-+	  }
-       }
--
-+    
-     // Set up new node.
--    Node n = new Node(key, value, RED);
-+    Node n = new Node(key, value);
-+    n.color = RED;
-     n.parent = parent;
--
-+    n.left = nil;
-+    n.right = nil;
-+    
-     // Insert node in tree.
--    modCount++;
-     size++;
-     if (parent == nil)
-       {
--        // Special case inserting into an empty tree.
--        root = n;
--        return null;
-+        // Special case: inserting into an empty tree.
-+	root = n;
-+	n.color = BLACK;
-+	return null;
-       }
--    if (comparison > 0)
-+    else if (comparison > 0)
-       parent.right = n;
-     else
--      parent.left = n;
--
-+      parent.left = n;   
-+    
-     // Rebalance after insert.
-     insertFixup(n);
-+    //verifyTree();
-     return null;
-   }
- 
--  /**
--   * Copies all elements of the given map into this hashtable.  If this table
--   * already has a mapping for a key, the new mapping replaces the current
--   * one.
--   *
--   * @param m the map to be hashed into this
--   * @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 m)
--  {
--    Iterator itr = m.entrySet().iterator();
--    int pos = m.size();
--    while (--pos >= 0)
--      {
--        Map.Entry e = (Map.Entry) 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 Object remove(Object key)
--  {
--    Node n = getNode(key);
--    if (n == nil)
--      return null;
--    removeNode(n);
--    return n.value;
--  }
--
--  /**
--   * 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.
--   *
--   * @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 subMap(Object fromKey, Object toKey)
--  {
--    return new SubMap(fromKey, 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.
--   *
--   * @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 tailMap(Object fromKey)
--  {
--    return new SubMap(fromKey, 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 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()
--      {
--        public int size()
--        {
--          return size;
--        }
--
--        public Iterator 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(Object o1, Object 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 node, Node parent)
-+  /** Maintain red-black balance after inserting a new node. */
-+  private void insertFixup(Node n)
-   {
--    // 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)
-+    // 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).
-+    while (n != root && n.parent.parent != nil && n.parent.color == RED)
-       {
--        if (node == parent.left)
--          {
--            // Rebalance left side.
--            Node 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;
-+	if (n.parent == n.parent.parent.left)
-+	  {
-+            Node uncle = n.parent.parent.right;
-+            if (uncle != nil && uncle.color == RED) 
-+	      {
-+        	n.parent.color = BLACK;
-+        	uncle.color = BLACK;
-+        	n.parent.parent.color = RED;
-+        	n = n.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;
-+	    else // Uncle is BLACK.
-+	      {                
-+                if (n == n.parent.right)
-+		  {
-+                    // Make n a left child.
-+                    n = n.parent;
-+                    rotateLeft(n);
-                   }
--                // 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 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;
-+                // Recolor and rotate.
-+                n.parent.color = BLACK;
-+                n.parent.parent.color = RED;
-+                rotateRight(n.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.
-+	  }
-+	else
-+	  {
-+	    // Mirror image of above code.
-+	    Node uncle = n.parent.parent.left;
-+            if (uncle != nil && uncle.color == RED)
-+	      {
-+                n.parent.color = BLACK;
-+                uncle.color = BLACK;
-+                n.parent.parent.color = RED;
-+                n = n.parent.parent;
-               }
--          }
-+	    else
-+	      {
-+                if (n == n.parent.left)
-+		  {
-+                    n = n.parent;
-+                    rotateRight(n);
-+                  }
-+                n.parent.color = BLACK;
-+                n.parent.parent.color = RED;
-+                rotateLeft(n.parent.parent);
-+	      }
-+	  }
-       }
--    node.color = BLACK;
-+    root.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)
-+  public void putAll(Map m)
-   {
--    if (count == 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;
-+    Iterator itr = m.entrySet().iterator();
-+    int msize = m.size();
-+    Map.Entry e;
- 
--    // Fill each row that is completely full of nodes.
--    for (rowsize = 2; rowsize + rowsize < count; rowsize <<= 1)
-+    for (int i = 0; i < msize; i++)
-       {
--        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;
-+	e = (Map.Entry) itr.next();
-+	put(e.getKey(), e.getValue());
-       }
-   }
- 
--  /**
--   * 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 firstNode()
-+  public Object remove(Object key)
-   {
--    // Exploit fact that nil.left == nil.
--    Node node = root;
--    while (node.left != nil)
--      node = node.left;
--    return node;
-+    Node n = getNode(key);
-+    if (n != nil)
-+      {
-+        removeNode(n);
-+	return n.value;
-+      }
-+    return null;
-   }
-+  
-+  // Remove node from tree. This will increment modCount and decrement size. 
-+  // Node must exist in the tree.
-+  private void removeNode(Node node) // z
-+  {
-+    Node splice; // y
-+    Node child;  // x
-+    
-+    modCount++;
-+    size--;
- 
--  /**
--   * 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 getNode(Object key)
--  {
--    Node current = root;
--    while (current != nil)
-+    // Find splice, the node at the position to actually remove from the tree. 
-+    if (node.left == nil || node.right == nil)
-       {
--        int comparison = compare(key, current.key);
--        if (comparison > 0)
--          current = current.right;
--        else if (comparison < 0)
--          current = current.left;
--        else
--          return current;
-+	// Node to be deleted has 0 or 1 children.
-+        splice = node;
-+	if (node.left == nil)
-+	  child = node.right;
-+	else
-+	  child = node.left;
-+      }
-+    else
-+      {
-+	// Node has 2 children. Splice is node's successor, and will be 
-+	// swapped with node since we can't remove node directly.
-+        splice = node.right;
-+        while (splice.left != nil)
-+	  splice = splice.left;
-+	child = splice.right;
-       }
--    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 highestLessThan(Object key)
--  {
--    if (key == nil)
--      return lastNode();
-+    // Unlink splice from the tree.
-+    Node parent = splice.parent;
-+    child.parent = parent;
-+    if (parent != nil)
-+      {
-+	if (splice == parent.left)
-+          parent.left = child;
-+	else
-+          parent.right = child;
-+      }
-+    else
-+      root = child;
- 
--    Node last = nil;
--    Node current = root;
--    int comparison = 0;
-+    // Keep track of splice's color in case it gets changed in the swap.
-+    int spliceColor = splice.color;
- 
--    while (current != nil)
-+/*
-+    if (splice != node)
-       {
--        last = current;
--        comparison = compare(key, current.key);
--        if (comparison > 0)
--          current = current.right;
--        else if (comparison < 0)
--          current = current.left;
--        else // Exact match.
--          return predecessor(last);
-+        node.key = splice.key;
-+	node.value = splice.value;
-+      }
-+*/
-+    if (splice != node)
-+      {
-+        // Swap SPLICE for NODE. Some implementations optimize here by simply
-+	// swapping the values, but we can't do that: if an iterator was
-+	// referencing a node in its "next" field, and that node got swapped, 
-+	// things would get confused.
-+	if (node == root)
-+	  {
-+	    root = splice;
-+	  }
-+	else
-+	  {
-+	    if (node.parent.left == node)
-+	      node.parent.left = splice;
-+	    else
-+	      node.parent.right = splice;
-+          }
-+	splice.parent = node.parent;
-+	splice.left = node.left;
-+	splice.right = node.right;
-+	splice.left.parent = splice;
-+	splice.right.parent = splice;
-+	splice.color = node.color;
-       }
--    return comparison <= 0 ? predecessor(last) : last;
-+
-+    if (spliceColor == BLACK)
-+      deleteFixup (child);
-+    
-+    //verifyTree();      
-   }
- 
--  /**
--   * Maintain red-black balance after inserting a new node.
--   *
--   * @param n the newly inserted node
--   */
--  private void insertFixup(Node n)
-+  /** Maintain red-black balance after deleting a node. */
-+  private void deleteFixup (Node node)
-   {
--    // 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)
-+    // A black node has been removed, so 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 (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)
-+        if (node == node.parent.left)
-+	  {
-+	    // Rebalance left side.
-+	    Node sibling = node.parent.right;
-+	    if (sibling.color == RED)
-+	      {
-+                sibling.color = BLACK;
-+                node.parent.color = RED;
-+                rotateLeft(node.parent);
-+                sibling = node.parent.right;
-+	      }
-+
-+	    if (sibling.left.color == BLACK && sibling.right.color == BLACK)
-               {
--                // 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;
-+	        // Case 2: Sibling has no red children.
-+		sibling.color = RED;
-+		// Black height has been decreased, so move up the tree and 
-+		// repeat.
-+		node = node.parent;
-               }
--            else
-+	    else
-+	      {	      
-+	        if (sibling.right.color == BLACK)
-+		  {
-+		    // Case 3: Sibling has red left child.
-+		    sibling.left.color = BLACK;
-+		    sibling.color = RED;
-+                    rotateRight(sibling);
-+                    sibling = node.parent.right;
-+		  }		  
-+		
-+		// Case 4: Sibling has red right child.
-+		sibling.color = sibling.parent.color;
-+		sibling.parent.color = BLACK;
-+		sibling.right.color = BLACK;
-+                rotateLeft(node.parent);
-+                node = root; // Finished.
-+	      }
-+	  }
-+	else
-+	  {
-+	    // Symmetric "mirror" of left-side case.
-+	    Node sibling = node.parent.left;
-+	    if (sibling.color == RED)
-+	      {
-+                sibling.color = BLACK;
-+                node.parent.color = RED;
-+                rotateRight(node.parent);
-+                sibling = node.parent.left;
-+	      }
-+
-+	    if (sibling.left.color == BLACK && sibling.right.color == BLACK)
-               {
--                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);
-+		sibling.color = RED;
-+		node = node.parent;
-               }
--          }
-+	    else
-+	      {	      
-+	        if (sibling.left.color == BLACK)
-+		  {
-+		    sibling.right.color = BLACK;
-+		    sibling.color = RED;
-+                    rotateLeft(sibling);
-+                    sibling = node.parent.left;
-+		  }		  
-+		
-+		sibling.color = sibling.parent.color;
-+		sibling.parent.color = BLACK;
-+		sibling.left.color = BLACK;
-+                rotateRight(node.parent);
-+                node = root;
-+	      }
-+	  }
-       }
--    root.color = BLACK;
-+    node.color = BLACK;
-   }
- 
--  /**
--   * Returns the last sorted node in the map, or nil if empty.
--   *
--   * @return the last node
--   */
--  private Node lastNode()
-+  public SortedMap subMap(Object fromKey, Object toKey)
-   {
--    // Exploit fact that nil.right == nil.
--    Node node = root;
--    while (node.right != nil)
--      node = node.right;
--    return node;
-+    if (compare(fromKey, toKey) <= 0)
-+      return new SubMap(fromKey, toKey);
-+    else
-+      throw new IllegalArgumentException("fromKey > toKey");
-   }
- 
--  /**
--   * 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 lowestGreaterThan(Object key, boolean first)
-+  public SortedMap headMap(Object toKey)
-   {
--    if (key == nil)
--      return first ? firstNode() : nil;
-+    return new SubMap(nil, toKey);
-+  }
-+
-+  public SortedMap tailMap(Object fromKey)
-+  {
-+    return new SubMap(fromKey, nil);
-+  }
-+
-+  /** Returns a "collection view" (or "bag view") of this TreeMap's values. */
-+  public Collection values()
-+  {
-+    // We don't bother overriding many of the optional methods, as doing so
-+    // wouldn't provide any significant performance advantage.
-+    return new AbstractCollection()
-+    {
-+      public int size()
-+      {
-+        return size;
-+      }
-+      
-+      public Iterator iterator()
-+      {
-+        return new TreeIterator(TreeIterator.VALUES);
-+      }
-+      
-+      public void clear()
-+      {
-+        TreeMap.this.clear();
-+      }
-+    };
-+  }
- 
-+  // Find the "highest" node which is < key. If key is nil, return last node.
-+  // Note that highestLessThan is exclusive (it won't return a key which is
-+  // equal to "key"), while lowestGreaterThan is inclusive, in order to be 
-+  // consistent with the semantics of subMap().
-+  private Node highestLessThan(Object key)
-+  {
-+    if (key == nil)
-+      return lastNode();
-+  
-     Node last = nil;
-     Node current = root;
-     int comparison = 0;
-@@ -1086,176 +734,122 @@
-       {
-         last = current;
-         comparison = compare(key, current.key);
--        if (comparison > 0)
--          current = current.right;
--        else if (comparison < 0)
--          current = current.left;
--        else
--          return current;
-+	if (comparison > 0)
-+	  current = current.right;
-+	else if (comparison < 0)
-+	  current = current.left;
-+	else /* Exact match. */
-+	  return predecessor(last);
-       }
--    return comparison > 0 ? successor(last) : last;
-+    if (comparison <= 0)
-+      return predecessor(last);
-+    else
-+      return 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 predecessor(Node node)
-+  // Find the "lowest" node which is >= key. If key is nil, return first node.
-+  private Node lowestGreaterThan(Object key)
-   {
--    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;
--  }
-+    if (key == nil)
-+      return firstNode();
- 
--  /**
--   * 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 readValue 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();
-+    Node last = nil;
-+    Node current = root;
-+    int comparison = 0;
- 
--    while (--count >= 0)
-+    while (current != nil)
-       {
--        node.key = s.readObject();
--        node.value = readValues ? s.readObject() : "";
--        node = successor(node);
-+        last = current;
-+        comparison = compare(key, current.key);
-+	if (comparison > 0)
-+	  current = current.right;
-+	else if (comparison < 0)
-+	  current = current.left;
-+	else
-+	  return current;
-       }
--  }
-+    if (comparison > 0)
-+      return successor(last);
-+    else
-+      return last;
-+  }  
- 
--  /**
--   * Construct a tree from sorted keys in linear time, with values of "".
--   * Package visible for use by TreeSet.
--   *
--   * @param keys the iterator over the sorted keys
--   * @param count the number of nodes to insert
--   * @see TreeSet#TreeSet(SortedSet)
--   */
--  final void putKeysLinear(Iterator keys, int count)
-+  private void writeObject(ObjectOutputStream out) throws IOException
-   {
--    fabricateTree(count);
--    Node node = firstNode();
-+    out.defaultWriteObject();
- 
--    while (--count >= 0)
-+    Node node = firstNode();
-+    out.writeInt(size);
-+    
-+    while (node != nil)
-       {
--        node.key = keys.next();
--        node.value = "";
--        node = successor(node);
-+        out.writeObject(node.key);
-+	out.writeObject(node.value);
-+	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)
-+  private void readObject(ObjectInputStream in)
-     throws IOException, ClassNotFoundException
-   {
--    s.defaultReadObject();
--    int size = s.readInt();
--    putFromObjStream(s, size, true);
-+    in.defaultReadObject();
-+    int size = in.readInt();
-+    putFromObjStream(in, 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 node)
-+  private int compare(Object o1, Object o2)
-   {
--    Node splice;
--    Node child;
--
--    modCount++;
--    size--;
-+    if (comparator == null)
-+      return ((Comparable) o1).compareTo(o2);
-+    else
-+      return comparator.compare(o1, o2);
-+  }
- 
--    // Find splice, the node at the position to actually remove from the tree.
--    if (node.left == nil)
-+  /* Return the node following Node, or nil if there isn't one. */
-+  private Node successor(Node node)
-+  {
-+    if (node.right != nil)
-       {
--        // Node to be deleted has 0 or 1 children.
--        splice = node;
--        child = node.right;
-+        node = node.right;
-+	while (node.left != nil)
-+	  node = node.left;
-+	return node;
-       }
--    else if (node.right == nil)
-+
-+    Node parent = node.parent;
-+    while (parent != nil && node == parent.right)
-       {
--        // Node to be deleted has 1 child.
--        splice = node;
--        child = node.left;
-+	node = parent;
-+	parent = parent.parent;
-       }
--    else
-+    return parent;
-+  }
-+
-+  /* Return the node preceeding Node, or nil if there isn't one. */
-+  private Node predecessor(Node node)
-+  {
-+    if (node.left != nil)
-       {
--        // 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;
-+        node = node.left;
-+	while (node.right != nil)
-+	  node = node.right;
-+	return node;
-       }
--
--    // Unlink splice from the tree.
--    Node parent = splice.parent;
--    if (child != nil)
--      child.parent = parent;
--    if (parent == nil)
-+      
-+    Node parent = node.parent;
-+    while (parent != nil && node == parent.left)
-       {
--        // Special case for 0 or 1 node remaining.
--        root = child;
--        return;
-+	node = parent;
-+	parent = parent.parent;
-       }
--    if (splice == parent.left)
--      parent.left = child;
--    else
--      parent.right = child;
--
--    if (splice.color == BLACK)
--      deleteFixup(child, parent);
-+    return parent;
-   }
- 
--  /**
--   * Rotate node n to the left.
--   *
--   * @param node the node to rotate
--   */
-+  /** Rotate node n to the left. */
-   private void rotateLeft(Node 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)
-@@ -1266,146 +860,331 @@
-     if (node.parent != nil)
-       {
-         if (node == node.parent.left)
--          node.parent.left = child;
--        else
--          node.parent.right = child;
-+	  node.parent.left = child;
-+	else
-+	  node.parent.right = child;
-       }
-     else
-       root = child;
- 
-     // Link n and child.
-     child.left = node;
--    node.parent = child;
-+    if (node != nil)
-+      node.parent = child;
-   }
- 
--  /**
--   * Rotate node n to the right.
--   *
--   * @param node the node to rotate
--   */
-+  /** Rotate node n to the right. */
-   private void rotateRight(Node 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;
-+	  node.parent.right = child;
-+	else
-+	  node.parent.left = child;
-       }
-     else
-       root = child;
--
-+    
-     // Link n and child.
-     child.right = node;
--    node.parent = child;
-+    if (node != nil)
-+      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 successor(Node node)
-+  
-+  /* Construct a tree from sorted keys in linear time. This is used to
-+     implement TreeSet's SortedSet constructor. */
-+  void putKeysLinear(Iterator keys, int count)
-   {
--    if (node.right != nil)
-+    fabricateTree(count);    
-+    Node node = firstNode();
-+    
-+    for (int i = 0; i < count; i++)
-       {
--        node = node.right;
--        while (node.left != nil)
--          node = node.left;
--        return node;
-+	node.key = keys.next();
-+	node.value = Boolean.TRUE;
-+	node = successor(node);
-       }
--
--    Node parent = node.parent;
--    // Exploit fact that nil.right == nil and node is non-nil.
--    while (node == parent.right)
-+  }
-+  
-+  /* As above, but load keys from an ObjectInputStream. Used by readObject()
-+     methods. If "readValues" is set, entry values will also be read from the 
-+     stream. If not, only keys will be read. */
-+  void putFromObjStream(ObjectInputStream in, int count, boolean readValues) 
-+    throws IOException, ClassNotFoundException
-+  {
-+    fabricateTree(count);    
-+    Node node = firstNode();
-+    
-+    for (int i = 0; i < count; i++)
-       {
--        node = parent;
--        parent = parent.parent;
--      }
--    return parent;
-+	node.key = in.readObject();
-+	if (readValues)
-+	  node.value = in.readObject();
-+	else
-+	  node.value = Boolean.TRUE;	  
-+	node = successor(node);
-+      }
-+  }
-+     
-+  /* Construct a perfectly balanced tree consisting of n "blank" nodes. 
-+     This permits a tree to be generated from pre-sorted input in linear 
-+     time. */
-+  private void fabricateTree(int count)
-+  {
-+    if (count == 0)
-+      return;
-+    // Calculate the (maximum) depth of the perfectly balanced tree.
-+    double ddepth = (Math.log (count + 1) / Math.log (2));
-+    int maxdepth = (int) Math.ceil (ddepth);
-+    
-+    // The number of nodes which can fit in a perfectly-balanced tree of 
-+    // height "depth - 1".
-+    int max = (int) Math.pow (2, maxdepth - 1) - 1;
-+    
-+    // Number of nodes which spill over into the deepest row of the tree.
-+    int overflow = (int) count - max;
-+    
-+    size = count;
-+    // Make the root node.
-+    root = new Node(null, null);
-+    root.parent = nil;
-+    root.left = nil;
-+    root.right = nil;
-+    
-+    Node row = root;
-+    for (int depth = 2; depth <= maxdepth; depth++)  // each row
-+      {	
-+	// Number of nodes at this depth
-+	int rowcap = (int) Math.pow (2, depth - 1);
-+	Node parent = row;
-+	Node last = null;
-+	
-+	// Actual number of nodes to create in this row
-+	int rowsize;
-+	if (depth == maxdepth)
-+	  rowsize = overflow;
-+	else
-+	  rowsize = rowcap;
-+	
-+	// The bottom most row of nodes is coloured red, as is every second row 
-+	// going up, except the root node (row 1). I'm not sure if this is the 
-+	// optimal configuration for the tree, but it seems logical enough.
-+	// We just need to honour the black-height and red-parent rules here.
-+	boolean colorRowRed = (depth % 2 == maxdepth % 2);
-+	
-+	int i;
-+	for (i = 1; i <= rowsize; i++)  // each node in row
-+	  {
-+	    Node node = new Node(null, null);
-+	    node.parent = parent;
-+	    if (i % 2 == 1)
-+	      parent.left = node;
-+	    else
-+	      {
-+		Node nextparent = parent.right;
-+		parent.right = node;
-+		parent = nextparent;
-+	      }
-+
-+	    // We use the "right" link to maintain a chain of nodes in 
-+	    // each row until the parent->child links are established.
-+	    if (last != null)
-+	      last.right = node;
-+	    last = node;
-+	    
-+	    if (colorRowRed)
-+	      node.color = RED;
-+	    
-+	    if (i == 1)
-+	      row = node;
-+	  }
-+
-+        // Set nil child pointers on leaf nodes.
-+	if (depth == maxdepth)
-+	  {
-+	    // leaf nodes at maxdepth-1.
-+	    if (parent != null)
-+	      {
-+		if (i % 2 == 0)
-+		  {
-+	            // Current "parent" has "left" set already.
-+		    Node next = parent.right;
-+		    parent.right = nil;
-+		    parent = next;
-+		  }		  		  
-+		while (parent != null)
-+		  {
-+		    parent.left = nil;
-+		    Node next = parent.right;
-+		    parent.right = nil;
-+		    parent = next;
-+		  }
-+	      }
-+	    // leaf nodes at maxdepth.
-+	    Node node = row;
-+	    Node next;
-+	    while (node != null)
-+	      {
-+	        node.left = nil;
-+		next = node.right;
-+		node.right = nil;
-+		node = next;
-+	      }
-+	  }
-+      }
-+  }
-+  
-+  private class VerifyResult
-+  {
-+    int count; // Total number of nodes.
-+    int black; // Black height/depth.
-+    int maxdepth; // Maximum depth of branch.
-   }
- 
--  /**
--   * 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
-+  /* Check that red-black properties are consistent for the tree. */
-+  private void verifyTree()
-   {
--    s.defaultWriteObject();
--
--    Node node = firstNode();
--    s.writeInt(size);
--    while (node != nil)
-+    if (root == nil)
-+      {
-+        System.err.println ("Verify: empty tree");
-+	if (size != 0)
-+	  verifyError (this, "no root node but size=" + size);
-+	return;
-+      }
-+    VerifyResult vr = verifySub (root);
-+    if (vr.count != size)
-+      {
-+	verifyError (this, "Tree size not consistent with actual nodes counted. "
-+                     + "counted " + vr.count + ", size=" + size);
-+        System.exit(1);
-+      }
-+    System.err.println ("Verify: " + vr.count + " nodes, black height=" + vr.black
-+                        + ", maxdepth=" + vr.maxdepth);
-+  }
-+  
-+  /* Recursive call to check that rbtree rules hold. Returns total node count
-+     and black height of the given branch. */
-+  private VerifyResult verifySub(Node n)
-+  {
-+    VerifyResult vr1 = null;
-+    VerifyResult vr2 = null;
-+    
-+    if (n.left == nil && n.right == nil)
-+      {
-+        // leaf node
-+	VerifyResult r = new VerifyResult();
-+	r.black = (n.color == BLACK ? 1 : 0);
-+	r.count = 1;
-+	r.maxdepth = 1;
-+	return r;
-+      }
-+    
-+    if (n.left != nil)
-+      {
-+        if (n.left.parent != n)
-+	  verifyError(n.left, "Node's parent link does not point to " + n);
-+	
-+	if (n.color == RED && n.left.color == RED)
-+	  verifyError(n, "Red node has red left child");
-+	
-+	vr1 = verifySub (n.left);
-+	if (n.right == nil)
-+	  {
-+	    if (n.color == BLACK)
-+	      vr1.black++;
-+	    vr1.count++;
-+	    vr1.maxdepth++;
-+	    return vr1;
-+	  }
-+      }
-+
-+    if (n.right != nil)
-+      {
-+        if (n.right.parent != n)
-+	  verifyError(n.right, "Node's parent link does not point to " + n);
-+
-+	if (n.color == RED && n.right.color == RED)
-+	  verifyError(n, "Red node has red right child");
-+
-+	vr2 = verifySub (n.right);
-+	if (n.left == nil)
-+	  {
-+	    if (n.color == BLACK)
-+	      vr2.black++;
-+	    vr2.count++;
-+	    vr2.maxdepth++;
-+	    return vr2;
-+	  }
-+      }
-+    
-+    if (vr1.black != vr2.black)
-+      verifyError (n, "Black heights: " + vr1.black + "," + vr2.black + " don't match.");
-+    vr1.count += vr2.count + 1;
-+    vr1.maxdepth = Math.max(vr1.maxdepth, vr2.maxdepth) + 1;
-+    if (n.color == BLACK)
-+      vr1.black++;
-+    return vr1;
-+  }
-+  
-+  private void verifyError (Object obj, String msg)
-+  {
-+    System.err.print ("Verify error: ");
-+    try
-+      {
-+        System.err.print (obj);
-+      }
-+    catch (Exception x)
-       {
--        s.writeObject(node.key);
--        s.writeObject(node.value);
--        node = successor(node);
-+        System.err.print ("(error printing obj): " + x);
-       }
-+    System.err.println();
-+    System.err.println (msg);
-+    Thread.dumpStack();
-+    System.exit(1);
-   }
- 
-   /**
--   * Iterate over HashMap'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}
--     */
-+   * Iterate over HashMap's entries.
-+   * This implementation is parameterized to give a sequential view of
-+   * keys, values, or entries.
-+   */   
-+  class TreeIterator implements Iterator
-+  {
-+    static final int ENTRIES = 0,
-+                     KEYS = 1,
-+                     VALUES = 2;  
-+  
-+    // the type of this Iterator: KEYS, VALUES, or ENTRIES.
-+    int type;
-+    // the number of modifications to the backing Map that we know about.
-+    int knownMod = TreeMap.this.modCount;
-+    // The last Entry returned by a next() call.
-+    Node last;
-+    // The next entry that should be returned by next().
-+    Node next;
-+    // The last node visible to this iterator. This is used when iterating
-+    // on a SubMap.
-+    Node max;
-+
-+    /* Create Iterator with the supplied type: KEYS, VALUES, or ENTRIES */
-     TreeIterator(int type)
-     {
--      // FIXME gcj cannot handle this. Bug java/4695
--      // this(type, firstNode(), nil);
-       this.type = type;
-       this.next = firstNode();
--      this.max = 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
--     */
-+    
-+    /* Construct an interator for a SubMap. Iteration will begin at node
-+       "first", and stop when "max" is reached. */    
-     TreeIterator(int type, Node first, Node max)
-     {
-       this.type = type;
-@@ -1413,351 +1192,263 @@
-       this.max = max;
-     }
- 
--    /**
--     * Returns true if the Iterator has more elements.
--     * @return true if there are more elements
--     * @throws ConcurrentModificationException if the TreeMap was modified
--     */
-     public boolean hasNext()
-     {
--      if (knownMod != modCount)
--        throw new ConcurrentModificationException();
--      return next != max;
-+      if (knownMod != TreeMap.this.modCount)
-+	throw new ConcurrentModificationException();
-+      return (next != nil);
-     }
- 
--    /**
--     * 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 (next == nil)
-+	throw new NoSuchElementException();
-+      if (knownMod != TreeMap.this.modCount)
-+	throw new ConcurrentModificationException();
-+      Node n = next;
-+
-+      // Check limit in case we are iterating through a submap.
-+      if (n != max)
-+	next = successor(n);
-+      else
-+        next = nil;
-+      
-+      last = n;
-+      
-       if (type == VALUES)
--        return last.value;
-+        return n.value;
-       else if (type == KEYS)
--        return last.key;
--      return last;
-+        return n.key;
-+      return n;
-     }
- 
--    /**
--     * 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 (knownMod != modCount)
--        throw new ConcurrentModificationException();
-       if (last == null)
--        throw new IllegalStateException();
--
--      removeNode(last);
--      last = null;
-+	throw new IllegalStateException();
-+      if (knownMod != TreeMap.this.modCount)
-+	throw new ConcurrentModificationException();
-+/*
-+      Object key = null;
-+      if (next != nil)
-+        key = next.key;
-+*/
-+      TreeMap.this.removeNode(last);
-       knownMod++;
-+/*
-+      if (key != null)
-+        next = getNode(key);
-+*/	
-+      last = null;
-     }
--  } // 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 implements SortedMap
-+  class SubMap extends AbstractMap implements SortedMap
-   {
--    /**
--     * The lower range of this view, inclusive, or nil for unbounded.
--     * Package visible for use by nested classes.
--     */
--    final Object minKey;
--
--    /**
--     * The upper range of this view, exclusive, or nil for unbounded.
--     * Package visible for use by nested classes.
--     */
--    final Object maxKey;
--
--    /**
--     * The cache for {@link #entrySet()}.
--     */
--    private Set entries;
--
--    /**
--     * 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
--     */
-+    Object minKey;
-+    Object maxKey;
-+
-+    /* Create a SubMap representing the elements between minKey and maxKey
-+       (inclusive). If minKey is nil, SubMap has no lower bound (headMap).
-+       If maxKey is nil, the SubMap has no upper bound (tailMap). */
-     SubMap(Object minKey, Object 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
--     */
--    final boolean keyInRange(Object key)
--    {
--      return ((minKey == nil || compare(key, minKey) >= 0)
--              && (maxKey == nil || compare(key, maxKey) < 0));
--    }
--
-     public void clear()
-     {
--      Node next = lowestGreaterThan(minKey, true);
--      Node max = lowestGreaterThan(maxKey, false);
--      while (next != max)
-+      Node current;
-+      Node next = lowestGreaterThan(minKey);
-+      Node max = highestLessThan(maxKey);
-+      
-+      if (compare(next.key, max.key) > 0)
-+        // Nothing to delete.
-+	return;
-+        
-+      do
-         {
--          Node current = next;
--          next = successor(current);
--          removeNode(current);
--        }
--    }
--
--    public Comparator comparator()
-+	  current = next;
-+	  next = successor(current);
-+	  remove(current);
-+	}
-+      while (current != max);
-+    }
-+    
-+    /* Check if "key" is in within the range bounds for this SubMap. 
-+       The lower ("from") SubMap range is inclusive, and the upper (to) bound
-+       is exclusive. */
-+    private boolean keyInRange(Object key)
-     {
--      return comparator;
-+      return ((minKey == nil || compare(key, minKey) >= 0)
-+	      && (maxKey == nil || compare(key, maxKey) < 0));
-     }
- 
-     public boolean containsKey(Object key)
-     {
--      return keyInRange(key) && TreeMap.this.containsKey(key);
-+      return (keyInRange(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 entrySet()
--    {
--      if (entries == null)
--        // Create an AbstractSet with custom implementations of those methods
--        // that can be overriden easily and efficiently.
--        entries = new AbstractSet()
--        {
--          public int size()
--          {
--            return SubMap.this.size();
--          }
--
--          public Iterator 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 me = (Map.Entry) o;
--            Object key = me.getKey();
--            if (! keyInRange(key))
--              return false;
--            Node 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 me = (Map.Entry) o;
--            Object key = me.getKey();
--            if (! keyInRange(key))
--              return false;
--            Node n = getNode(key);
--            if (n != nil && AbstractSet.equals(me.getValue(), n.value))
--              {
--                removeNode(n);
--                return true;
--              }
--            return false;
--          }
--        };
--      return entries;
--    }
--
--    public Object firstKey()
--    {
--      Node node = lowestGreaterThan(minKey, true);
--      if (node == nil || ! keyInRange(node.key))
--        throw new NoSuchElementException();
--      return node.key;
-+      Node node = lowestGreaterThan(minKey);
-+      Node max = highestLessThan(maxKey);
-+      Object currentVal;
-+
-+      if (node == nil || max == nil || compare(node.key, max.key) > 0)
-+        // Nothing to search.
-+	return false;
-+
-+      while (true)
-+	{
-+	  currentVal = node.getValue();
-+          if (value == null ? currentVal == null : value.equals (currentVal))
-+	    return true;
-+	  if (node == max)
-+	    return false;
-+	  node = successor(node);
-+	}
-     }
- 
-     public Object get(Object key)
-     {
-       if (keyInRange(key))
--        return TreeMap.this.get(key);
-+	return TreeMap.this.get(key);
-       return null;
-     }
- 
--    public SortedMap headMap(Object toKey)
-+    public Object put(Object key, Object value)
-     {
--      if (! keyInRange(toKey))
--        throw new IllegalArgumentException("key outside range");
--      return new SubMap(minKey, toKey);
-+      if (keyInRange(key))
-+	return TreeMap.this.put(key, value);
-+      else
-+	throw new IllegalArgumentException("Key outside range");
-     }
- 
--    public Set keySet()
-+    public Object remove(Object key)
-     {
--      if (this.keys == null)
--        // Create an AbstractSet with custom implementations of those methods
--        // that can be overriden easily and efficiently.
--        this.keys = new AbstractSet()
--        {
--          public int size()
--          {
--            return SubMap.this.size();
--          }
-+      if (keyInRange(key))
-+	return TreeMap.this.remove(key);
-+      else
-+        return null;
-+    }
- 
--          public Iterator iterator()
--          {
--            Node first = lowestGreaterThan(minKey, true);
--            Node max = lowestGreaterThan(maxKey, false);
--            return new TreeIterator(KEYS, first, max);
--          }
-+    public int size()
-+    {
-+      Node node = lowestGreaterThan(minKey);
-+      Node max = highestLessThan(maxKey);
- 
--          public void clear()
--          {
--            SubMap.this.clear();
--          }
-+      if (node == nil || max == nil || compare(node.key, max.key) > 0)
-+	return 0;  // Empty.
- 
--          public boolean contains(Object o)
--          {
--            if (! keyInRange(o))
--              return false;
--            return getNode(o) != nil;
--          }
-+      int count = 1;
-+      while (node != max)
-+        {
-+	  count++;
-+	  node = successor(node);
-+	}
- 
--          public boolean remove(Object o)
--          {
--            if (! keyInRange(o))
--              return false;
--            Node n = getNode(o);
--            if (n != nil)
--              {
--                removeNode(n);
--                return true;
--              }
--            return false;
--          }
--        };
--      return this.keys;
-+      return count;
-     }
- 
--    public Object lastKey()
-+    public Set entrySet()
-     {
--      Node node = highestLessThan(maxKey);
--      if (node == nil || ! keyInRange(node.key))
--        throw new NoSuchElementException();
--      return node.key;
-+      // Create an AbstractSet with custom implementations of those methods that 
-+      // can be overriden easily and efficiently.
-+      return new AbstractSet()
-+      {
-+	public int size()
-+	{
-+          return SubMap.this.size();
-+	}
-+
-+	public Iterator iterator()
-+	{
-+	  Node first = lowestGreaterThan(minKey);
-+	  Node max = highestLessThan(maxKey);
-+          return new TreeIterator(TreeIterator.ENTRIES, first, max);
-+	}
-+
-+	public void clear()
-+	{
-+          this.clear();
-+	}
-+
-+	public boolean contains(Object o)
-+	{
-+          if (!(o instanceof Map.Entry))
-+	    return false;
-+	  Map.Entry me = (Map.Entry) o;
-+	  Object key = me.getKey();
-+	  if (!keyInRange(key))
-+	    return false;
-+	  Node n = getNode(key);
-+	  return (n != nil && me.getValue().equals(n.value));
-+	}
-+
-+	public boolean remove(Object o)
-+	{
-+          if (!(o instanceof Map.Entry))
-+	    return false;
-+	  Map.Entry me = (Map.Entry) o;
-+	  Object key = me.getKey();
-+	  if (!keyInRange(key))
-+	    return false;
-+	  Node n = getNode(key);
-+	  if (n != nil && me.getValue().equals(n.value))
-+	    {
-+	      removeNode(n);
-+	      return true;
-+	    }
-+	  return false;
-+	}
-+      };    
-     }
- 
--    public Object put(Object key, Object value)
-+    public Comparator comparator()
-     {
--      if (! keyInRange(key))
--        throw new IllegalArgumentException("Key outside range");
--      return TreeMap.this.put(key, value);
-+      return comparator;
-     }
- 
--    public Object remove(Object key)
-+    public Object firstKey()
-     {
--      if (keyInRange(key))
--        return TreeMap.this.remove(key);
--      return null;
-+      Node node = lowestGreaterThan(minKey);
-+      if (node == nil || !keyInRange(node.key))
-+        throw new NoSuchElementException ("empty");
-+      return node.key;
-     }
- 
--    public int size()
-+    public Object lastKey()
-     {
--      Node node = lowestGreaterThan(minKey, true);
--      Node max = lowestGreaterThan(maxKey, false);
--      int count = 0;
--      while (node != max)
--        {
--          count++;
--          node = successor(node);
--        }
--      return count;
-+      Node node = highestLessThan(maxKey);
-+      if (node == nil || !keyInRange(node.key))
-+        throw new NoSuchElementException ("empty");
-+      return node.key;
-     }
- 
-     public SortedMap subMap(Object fromKey, Object toKey)
-     {
--      if (! keyInRange(fromKey) || ! keyInRange(toKey))
-+      if (!keyInRange(fromKey) || !keyInRange(toKey))
-         throw new IllegalArgumentException("key outside range");
--      return new SubMap(fromKey, toKey);
-+
-+      return TreeMap.this.subMap(fromKey, toKey);
-     }
- 
--    public SortedMap tailMap(Object fromKey)
-+    public SortedMap headMap(Object toKey)
-     {
--      if (! keyInRange(fromKey))
-+      if (!keyInRange(toKey))
-         throw new IllegalArgumentException("key outside range");
--      return new SubMap(fromKey, maxKey);
-+
-+      return TreeMap.this.subMap(minKey, toKey);
-     }
- 
--    public Collection values()
-+    public SortedMap tailMap(Object fromKey)
-     {
--      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 iterator()
--          {
--            Node first = lowestGreaterThan(minKey, true);
--            Node max = lowestGreaterThan(maxKey, false);
--            return new TreeIterator(VALUES, first, max);
--          }
-+      if (!keyInRange(fromKey))
-+        throw new IllegalArgumentException("key outside range");
- 
--          public void clear()
--          {
--            SubMap.this.clear();
--          }
--        };
--      return this.keys;
-+      return TreeMap.this.subMap(fromKey, maxKey);
-     }
 -  } // class SubMap
--} // class TreeMap
-+  }
-+}
++  } // class SubMap  
+ } // class TreeMap
Index: compare/java.util.TreeSet.diff
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/java/compare/java.util.TreeSet.diff,v
retrieving revision 1.1
diff -u -r1.1 java.util.TreeSet.diff
--- compare/java.util.TreeSet.diff 2001/11/07 01:23:49 1.1
+++ compare/java.util.TreeSet.diff 2001/12/16 00:14:01
@@ -1,480 +1,10 @@
 --- /home/tromey/gnu/egcs/classpath/classpath/java/util/TreeSet.java	Fri Oct 26 16:06:59 2001
-+++ java/util/TreeSet.java	Tue Oct 16 09:14:35 2001
-@@ -1,4 +1,4 @@
--/* TreeSet.java -- a class providing a TreeMap-backed SortedSet
-+/* TreeSet.java -- a class providing a TreeMap-backet SortedSet
-    Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
- 
- This file is part of GNU Classpath.
-@@ -33,90 +33,54 @@
- import java.io.ObjectOutputStream;
- 
- /**
-- * This class provides a TreeMap-backed implementation of the SortedSet
-- * interface. The elements will be sorted according to their <i>natural
-- * order</i>, or according to the provided <code>Comparator</code>.<p>
-+ * This class provides a TreeMap-backed implementation of the 
-+ * SortedSet interface.
++++ java/util/TreeSet.java	Sat Dec 15 09:16:05 2001
+@@ -55,6 +55,7 @@
+  * non-deterministic behavior.
   *
-- * Most operations are O(log n), but there is so much overhead that this
-- * makes small sets expensive. Note that the ordering must be <i>consistent
-- * with equals</i> to correctly implement the Set interface. If this
-- * condition is violated, the set is still well-behaved, but you may have
-- * suprising results when comparing it to other sets.<p>
-+ * Each element in the Set is a key in the backing TreeMap; each key
-+ * maps to a static token, denoting that the key does, in fact, exist.
-  *
-- * This implementation is not synchronized. If you need to share this between
-- * multiple threads, do something like:<br>
-- * <code>SortedSet s
-- *       = Collections.synchronizedSortedSet(new TreeSet(...));</code><p>
-+ * Most operations are O(log n).
-  *
-- * 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.
-+ * TreeSet is a part of the JDK1.2 Collections API.
-  *
-- * @author Jon Zeppieri
-- * @author Eric Blake <ebb9@email.byu.edu>
-- * @see Collection
-- * @see Set
-- * @see HashSet
-- * @see LinkedHashSet
-- * @see Comparable
-- * @see Comparator
-- * @see Collections#synchronizedSortedSet(SortedSet)
-- * @see TreeMap
-- * @since 1.2
-- * @status updated to 1.4
-+ * @author      Jon Zeppieri
-  */
-+
- public class TreeSet extends AbstractSet
-   implements SortedSet, Cloneable, Serializable
- {
--  /**
--   * Compatible with JDK 1.2.
--   */
--  private static final long serialVersionUID = -2479143000061671589L;
-+  /** The TreeMap which backs this Set */
-+  transient SortedMap map;
- 
--  /**
--   * The SortedMap which backs this Set.
--   */
--  // Not final because of readObject. This will always be one of TreeMap or
--  // TreeMap.SubMap, which both extend AbstractMap.
--  private transient SortedMap map;
-+  static final long serialVersionUID = -2479143000061671589L;
- 
-   /**
--   * Construct a new TreeSet whose backing TreeMap using the "natural"
--   * ordering of keys. Elements that are not mutually comparable will cause
--   * ClassCastExceptions down the road.
--   *
--   * @see Comparable
-+   * Construct a new TreeSet whose backing TreeMap using the "natural" 
-+   * ordering of keys.
-    */
-   public TreeSet()
-   {
-     map = new TreeMap();
-   }
- 
--  /**
--   * Construct a new TreeSet whose backing TreeMap uses the supplied
--   * Comparator. Elements that are not mutually comparable will cause
--   * ClassCastExceptions down the road.
-+  /** 
-+   * Construct a new TreeSet whose backing TreeMap uses the supplied 
-+   * Comparator.
-    *
--   * @param comparator the Comparator this Set will use
-+   * @param     oComparator      the Comparator this Set will use
-    */
-   public TreeSet(Comparator comparator)
-   {
-     map = new TreeMap(comparator);
-   }
- 
--  /**
-+  /** 
-    * Construct a new TreeSet whose backing TreeMap uses the "natural"
-    * orering of the keys and which contains all of the elements in the
--   * supplied Collection. This runs in n*log(n) time.
-+   * supplied Collection.
-    *
--   * @param collection the new Set will be initialized with all
--   *        of the elements in this Collection
--   * @throws ClassCastException if the elements of the collection are not
--   *         comparable
--   * @throws NullPointerException if the collection is null
--   * @see Comparable
-+   * @param     oCollection      the new Set will be initialized with all
-+   *                             of the elements in this Collection
-    */
-   public TreeSet(Collection collection)
-   {
-@@ -129,57 +93,54 @@
-    * SortedSet and containing all of the elements in the supplied SortedSet.
-    * This constructor runs in linear time.
-    *
--   * @param sortedSet the new TreeSet will use this SortedSet's comparator
--   *        and will initialize itself with all its elements
--   * @throws NullPointerException if sortedSet is null
-+   * @param     sortedSet       the new TreeSet will use this SortedSet's
-+   *                            comparator and will initialize itself
-+   *                            with all of the elements in this SortedSet
-    */
-   public TreeSet(SortedSet sortedSet)
-   {
--    map = new TreeMap(sortedSet.comparator());
-+    TreeMap map = new TreeMap(sortedSet.comparator());
-+    int i = 0;
-     Iterator itr = sortedSet.iterator();
--    ((TreeMap) map).putKeysLinear(itr, sortedSet.size());
-+    map.putKeysLinear(itr, sortedSet.size());
-+    this.map = map;
-   }
--
--  /**
--   * This private constructor is used to implement the subSet() calls around
--   * a backing TreeMap.SubMap.
--   *
--   * @param backingMap the submap
--   */
--  private TreeSet(SortedMap backingMap)
-+  
-+  /* This private constructor is used to implement the subSet() calls around
-+    a backing TreeMap.SubMap. */
-+  TreeSet(SortedMap backingMap)
-   {
-     map = backingMap;
-   }
- 
--  /**
-+  /** 
-    * Adds the spplied Object to the Set if it is not already in the Set;
--   * returns true if the element is added, false otherwise.
-+   * returns true if the element is added, false otherwise
-    *
--   * @param obj the Object to be added to this Set
--   * @throws ClassCastException if the element cannot be compared with objects
--   *         already in the set
-+   * @param       obj       the Object to be added to this Set
-    */
-   public boolean add(Object obj)
-   {
--    return map.put(obj, "") == null;
-+    return (map.put(obj, Boolean.TRUE) == null);
-   }
- 
-   /**
-    * Adds all of the elements in the supplied Collection to this TreeSet.
-    *
--   * @param c The collection to add
--   * @return true if the Set is altered, false otherwise
--   * @throws NullPointerException if c is null
--   * @throws ClassCastException if an element in c cannot be compared with
--   *         objects already in the set
-+   * @param        c         All of the elements in this Collection
-+   *                         will be added to the Set.
-+   *
-+   * @return       true if the Set is altered, false otherwise
-    */
-   public boolean addAll(Collection c)
-   {
-     boolean result = false;
--    int pos = c.size();
-+    int size = c.size();
-     Iterator itr = c.iterator();
--    while (--pos >= 0)
--      result |= (map.put(itr.next(), "") == null);
-+
-+    for (int i = 0; i < size; i++)
-+      result |= (map.put(itr.next(), Boolean.TRUE) == null);
-+
-     return result;
-   }
- 
-@@ -191,214 +152,137 @@
-     map.clear();
-   }
- 
--  /**
--   * Returns a shallow copy of this Set. The elements are not cloned.
--   *
--   * @return the cloned set
--   */
-+  /** Returns a shallow copy of this Set. */
-   public Object clone()
-   {
-     TreeSet copy = null;
-     try
-       {
-         copy = (TreeSet) super.clone();
--        // Map may be either TreeMap or TreeMap.SubMap, hence the ugly casts.
--        copy.map = (SortedMap) ((AbstractMap) map).clone();
-       }
-     catch (CloneNotSupportedException x)
--      {
--        // Impossible result.
-+      {      
-       }
-+    copy.map = (SortedMap) ((TreeMap) map).clone();
-     return copy;
-   }
- 
--  /**
--   * Returns this Set's comparator.
--   *
--   * @return the comparator, or null if the set uses natural ordering
--   */
-+  /** Returns this Set's comparator */
-   public Comparator comparator()
-   {
-     return map.comparator();
-   }
- 
--  /**
--   * Returns true if this Set contains the supplied Object, false otherwise.
-+  /** 
-+   * Returns true if this Set contains the supplied Object, 
-+   * false otherwise 
-    *
--   * @param obj the Object to check for
--   * @return true if it is in the set
--   * @throws ClassCastException if obj cannot be compared with objects
--   *         already in the set
-+   * @param       oObject        the Object whose existence in the Set is
-+   *                             being tested
-    */
-   public boolean contains(Object obj)
-   {
-     return map.containsKey(obj);
-   }
- 
--  /**
--   * Returns the first (by order) element in this Set.
--   *
--   * @return the first element
--   * @throws NoSuchElementException if the set is empty
--   */
--  public Object first()
-+  /** Returns true if this Set has size 0, false otherwise */
-+  public boolean isEmpty()
-   {
--    return map.firstKey();
-+    return map.isEmpty();
-   }
- 
--  /**
--   * Returns a view of this Set including all elements less than
--   * <code>to</code>. The returned set is backed by the original, so changes
--   * in one appear in the other. The subset will throw an
--   * {@link IllegalArgumentException} for any attempt to access or add an
--   * element beyond the specified cutoff. The returned set does not include
--   * the endpoint; if you want inclusion, pass the successor element.
--   *
--   * @param to the (exclusive) cutoff point
--   * @return a view of the set less than the cutoff
--   * @throws ClassCastException if <code>to</code> is not compatible with
--   *         the comparator (or is not Comparable, for natural ordering)
--   * @throws NullPointerException if to is null, but the comparator does not
--   *         tolerate null elements
--   */
--  public SortedSet headSet(Object to)
-+  /** Returns the number of elements in this Set */
-+  public int size()
-   {
--    return new TreeSet(map.headMap(to));
-+    return map.size();
-   }
- 
--  /**
--   * Returns true if this Set has size 0, false otherwise.
-+  /** 
-+   * If the supplied Object is in this Set, it is removed, and true is
-+   * returned; otherwise, false is returned.
-    *
--   * @return true if the set is empty
-+   * @param         obj        the Object we are attempting to remove
-+   *                           from this Set
-    */
--  public boolean isEmpty()
-+  public boolean remove(Object obj)
-   {
--    return map.isEmpty();
-+    return (map.remove(obj) != null);
-   }
- 
--  /**
--   * Returns in Iterator over the elements in this TreeSet, which traverses
--   * in ascending order.
--   *
--   * @return an iterator
--   */
--  public Iterator iterator()
-+  /** Returns the first (by order) element in this Set */
-+  public Object first()
-   {
--    return map.keySet().iterator();
-+    return map.firstKey();
-   }
- 
--  /**
--   * Returns the last (by order) element in this Set.
--   *
--   * @return the last element
--   * @throws NoSuchElementException if the set is empty
--   */
-+  /** Returns the last (by order) element in this Set */
-   public Object last()
-   {
-     return map.lastKey();
-   }
- 
-   /**
--   * If the supplied Object is in this Set, it is removed, and true is
--   * returned; otherwise, false is returned.
-+   * Returns a view of this Set including all elements in the interval
-+   * [oFromElement, oToElement).
-    *
--   * @param obj the Object to remove from this Set
--   * @return true if the set was modified
--   * @throws ClassCastException if obj cannot be compared to set elements
-+   * @param       from  the resultant view will contain all
-+   *                    elements greater than or equal to this element
-+   * @param       to    the resultant view will contain all
-+   *                    elements less than this element
-    */
--  public boolean remove(Object obj)
-+  public SortedSet subSet(Object from, Object to)
-   {
--    return map.remove(obj) != null;
-+    return new TreeSet(map.subMap(from, to));
-   }
- 
-   /**
--   * Returns the number of elements in this Set
-+   * Returns a view of this Set including all elements less than oToElement
-    *
--   * @return the set size
-+   * @param       toElement    the resultant view will contain all
-+   *                            elements less than this element
-    */
--  public int size()
-+  public SortedSet headSet(Object to)
-   {
--    return map.size();
-+    return new TreeSet(map.headMap(to));
-   }
- 
-   /**
--   * Returns a view of this Set including all elements greater or equal to
--   * <code>from</code> and less than <code>to</code> (a half-open interval).
--   * The returned set is backed by the original, so changes in one appear in
--   * the other. The subset will throw an {@link IllegalArgumentException}
--   * for any attempt to access or add an element beyond the specified cutoffs.
--   * The returned set includes the low endpoint but not the high; if you want
--   * to reverse this behavior on either end, pass in the successor element.
--   *
--   * @param from the (inclusive) low cutoff point
--   * @param to the (exclusive) high cutoff point
--   * @return a view of the set between the cutoffs
--   * @throws ClassCastException if either cutoff is not compatible with
--   *         the comparator (or is not Comparable, for natural ordering)
--   * @throws NullPointerException if from or to is null, but the comparator
--   *         does not tolerate null elements
--   * @throws IllegalArgumentException if from is greater than to
-+   * Returns a view of this Set including all elements greater than or
-+   * equal to oFromElement.
-+   *
-+   * @param       from  the resultant view will contain all
-+   *              elements greater than or equal to this element
-    */
--  public SortedSet subSet(Object from, Object to)
-+  public SortedSet tailSet(Object from)
-   {
--    return new TreeSet(map.subMap(from, to));
-+    return new TreeSet(map.tailMap(from));
-   }
- 
--  /**
--   * Returns a view of this Set including all elements greater or equal to
--   * <code>from</code>. The returned set is backed by the original, so
--   * changes in one appear in the other. The subset will throw an
--   * {@link IllegalArgumentException} for any attempt to access or add an
--   * element beyond the specified cutoff. The returned set includes the
--   * endpoint; if you want to exclude it, pass in the successor element.
--   *
--   * @param from the (inclusive) low cutoff point
--   * @return a view of the set above the cutoff
--   * @throws ClassCastException if <code>from</code> is not compatible with
--   *         the comparator (or is not Comparable, for natural ordering)
--   * @throws NullPointerException if from is null, but the comparator
--   *         does not tolerate null elements
--   */
--  public SortedSet tailSet(Object from)
-+  /** Returns in Iterator over the elements in this TreeSet */
-+  public Iterator iterator()
-   {
--    return new TreeSet(map.tailMap(from));
-+    return map.keySet().iterator();
-   }
- 
--  /**
--   * Serializes this object to the given stream.
--   *
--   * @param s the stream to write to
--   * @throws IOException if the underlying stream fails
--   * @serialData the <i>comparator</i> (Object), followed by the set size
--   *             (int), the the elements in sorted order (Object)
--   */
--  private void writeObject(ObjectOutputStream s) throws IOException
-+  private void writeObject(ObjectOutputStream out) throws IOException
-   {
--    s.defaultWriteObject();
-     Iterator itr = map.keySet().iterator();
--    int pos = map.size();
--    s.writeObject(map.comparator());
--    s.writeInt(pos);
--    while (--pos >= 0)
--      s.writeObject(itr.next());
-+    int size = map.size();
-+
-+    out.writeObject(map.comparator());
-+    out.writeInt(size);
-+
-+    for (int i = 0; i < size; i++)
-+      out.writeObject(itr.next());
-   }
- 
--  /**
--   * 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>comparator</i> (Object), followed by the set size
--   *             (int), the the elements in sorted order (Object)
--   */
--  private void readObject(ObjectInputStream s)
-+  private void readObject(ObjectInputStream in)
-     throws IOException, ClassNotFoundException
-   {
--    s.defaultReadObject();
--    Comparator comparator = (Comparator) s.readObject();
--    int size = s.readInt();
--    map = new TreeMap(comparator);
--    ((TreeMap) map).putFromObjStream(s, size, false);
-+    Comparator comparator = (Comparator) in.readObject();
-+    int size = in.readInt();
-+    TreeMap map = new TreeMap(comparator);    
-+    map.putFromObjStream(in, size, false);
-+    this.map = map;
-   }
- }
+  * @author Jon Zeppieri
++ * @author Bryce McKinlay
+  * @author Eric Blake <ebb9@email.byu.edu>
+  * @see Collection
+  * @see Set
Index: compare/java.util.Vector.diff
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/java/compare/java.util.Vector.diff,v
retrieving revision 1.1
diff -u -r1.1 java.util.Vector.diff
--- compare/java.util.Vector.diff 2001/11/07 01:23:49 1.1
+++ compare/java.util.Vector.diff 2001/12/16 00:14:01
@@ -1,1208 +1,10 @@
 --- /home/tromey/gnu/egcs/classpath/classpath/java/util/Vector.java	Fri Nov  2 09:28:56 2001
-+++ java/util/Vector.java	Fri Nov  2 21:44:52 2001
-@@ -1,5 +1,5 @@
- /* Vector.java -- Class that provides growable arrays.
--   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
-+   Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
- 
- This file is part of GNU Classpath.
- 
-@@ -30,72 +30,51 @@
- import java.io.Serializable;
- 
- /**
-- * The <code>Vector</code> classes implements growable arrays of Objects.
-+ * the <b>Vector</b> classes implements growable arrays of Objects.
-  * You can access elements in a Vector with an index, just as you
-  * can in a built in array, but Vectors can grow and shrink to accommodate
-- * more or fewer objects.<p>
-+ * more or fewer objects.  
++++ java/util/Vector.java	Sat Dec 15 09:16:05 2001
+@@ -58,6 +58,7 @@
+  * directly specify this subclass.
   *
-  * Vectors try to mantain efficiency in growing by having a
-- * <code>capacityIncrement</code> that can be specified at instantiation.
-+ * <b>capacityIncrement</b> that can be specified at instantiation.
-  * When a Vector can no longer hold a new Object, it grows by the amount
-- * in <code>capacityIncrement</code>. If this value is 0, the vector doubles in
-- * size.<p>
-+ * in <b>capacityIncrement</b>.  
-  *
-- * Vector implements the JDK 1.2 List interface, and is therefore a fully
-- * compliant Collection object. The iterators are fail-fast - if external
-- * code structurally modifies the vector, any operation on the iterator will
-- * then throw a {@link ConcurrentModificationException}. The Vector class is
-- * fully synchronized, but the iterators are not. So, when iterating over a
-- * vector, be sure to synchronize on the vector itself.  If you don't want the
-- * expense of synchronization, use ArrayList instead. On the other hand, the
-- * Enumeration of elements() is not thread-safe, nor is it fail-fast; so it
-- * can lead to undefined behavior even in a single thread if you modify the
-- * vector during iteration.<p>
-- *
-- * Note: Some methods, especially those specified by List, specify throwing
-- * {@link IndexOutOfBoundsException}, but it is easier to implement by
-- * throwing the subclass {@link ArrayIndexOutOfBoundsException}. Others
-- * directly specify this subclass.
-+ * Vector implements the JDK 1.2 List interface, and is therefor a fully
-+ * compliant Collection object.
-  *
-+ * @specnote The JCL claims that various methods in this class throw
-+ * IndexOutOfBoundsException, which would be consistent with other collections
-+ * classes. ArrayIndexOutOfBoundsException is actually thrown, per the online 
-+ * docs, even for List method implementations.
-+ * 
   * @author Scott G. Miller
-- * @author Eric Blake <ebb9@email.byu.edu>
-- * @see Collection
-- * @see List
-- * @see ArrayList
-- * @see LinkedList
-- * @since 1.0
-- * @status updated to 1.4
-  */
--public class Vector extends AbstractList
--  implements List, RandomAccess, Cloneable, Serializable
-+public class Vector extends AbstractList 
-+  implements List, Cloneable, Serializable
- {
-   /**
--   * Compatible with JDK 1.0+.
-+   * The amount the Vector's internal array should be increased in size when
-+   * a new element is added that exceeds the current size of the array,
-+   * or when {@link #ensureCapacity} is called.
-+   * @serial
-    */
--  private static final long serialVersionUID = -2767605614048989439L;
--
--  /**
--   * The internal array used to hold members of a Vector. The elements are
--   * in positions 0 through elementCount - 1, and all remaining slots are null.
--   * @serial the elements
--   */
--  protected Object[] elementData;
-+  protected int capacityIncrement = 0;
- 
-   /**
-    * The number of elements currently in the vector, also returned by
-    * {@link #size}.
--   * @serial the size
-+   * @serial
-    */
--  protected int elementCount;
-+  protected int elementCount = 0;
- 
-   /**
--   * The amount the Vector's internal array should be increased in size when
--   * a new element is added that exceeds the current size of the array,
--   * or when {@link #ensureCapacity} is called. If &lt;= 0, the vector just
--   * doubles in size.
--   * @serial the amount to grow the vector by
-+   * The internal array used to hold members of a Vector
-+   * @serial
-    */
--  protected int capacityIncrement;
-+  protected Object[] elementData;
-+
-+  private static final long serialVersionUID = -2767605614048989439L;
- 
-   /**
-    * Constructs an empty vector with an initial size of 10, and
-@@ -103,31 +82,36 @@
-    */
-   public Vector()
-   {
--    this(10, 0);
-+    this(10);
-   }
- 
-   /**
-    * Constructs a vector containing the contents of Collection, in the
--   * order given by the collection.
-+   * order given by the collection
-    *
--   * @param c collection of elements to add to the new vector
--   * @throws NullPointerException if c is null
--   * @since 1.2
-+   * @param c A collection of elements to be added to the newly constructed
-+   * vector
-    */
-   public Vector(Collection c)
-   {
--    elementCount = c.size();
--    elementData = c.toArray(new Object[elementCount]);
-+    int csize = c.size();
-+    elementData = new Object[csize];
-+    elementCount = csize;
-+    Iterator itr = c.iterator();
-+    for (int i = 0; i < csize; i++)
-+      {
-+	elementData[i] = itr.next();
-+      }
-   }
- 
-   /**
--   * Constructs a Vector with the initial capacity and capacity
--   * increment specified.
-+   * Constructs a Vector with the initial capacity and capacity 
-+   * increment specified
-    *
--   * @param initialCapacity the initial size of the Vector's internal array
--   * @param capacityIncrement the amount the internal array should be
--   *        increased by when necessary, 0 to double the size
--   * @throws IllegalArgumentException if initialCapacity &lt; 0
-+   * @param initialCapacity The initial size of the Vector's internal
-+   * array
-+   * @param capacityIncrement The amount the internal array should be
-+   * increased if necessary
-    */
-   public Vector(int initialCapacity, int capacityIncrement)
-   {
-@@ -138,37 +122,37 @@
-   }
- 
-   /**
--   * Constructs a Vector with the initial capacity specified, and a capacity
--   * increment of 0 (double in size).
-+   * Constructs a Vector with the initial capacity specified
-    *
--   * @param initialCapacity the initial size of the Vector's internal array
--   * @throws IllegalArgumentException if initialCapacity &lt; 0
-+   * @param initialCapacity The initial size of the Vector's internal array
-    */
-   public Vector(int initialCapacity)
-   {
--    this(initialCapacity, 0);
-+    if (initialCapacity < 0)
-+      throw new IllegalArgumentException();
-+    elementData = new Object[initialCapacity];
-   }
- 
-   /**
--   * Copies the contents of a provided array into the Vector.  If the
--   * array is too large to fit in the Vector, an IndexOutOfBoundsException
--   * is thrown without modifying the array.  Old elements in the Vector are
--   * overwritten by the new elements.
--   *
--   * @param a target array for the copy
--   * @throws IndexOutOfBoundsException the array is not large enough
--   * @throws NullPointerException the array is null
--   * @see #toArray(Object[])
-+   * Copies the contents of a provided array into the Vector.  If the 
-+   * array is too large to fit in the Vector, an ArrayIndexOutOfBoundsException
-+   * is thrown.  Old elements in the Vector are overwritten by the new
-+   * elements
-+   *
-+   * @param anArray An array from which elements will be copied into the Vector
-+   * 
-+   * @throws ArrayIndexOutOfBoundsException the array being copied
-+   * is larger than the Vectors internal data array
-    */
--  public synchronized void copyInto(Object[] a)
-+  public synchronized void copyInto(Object[] anArray)
-   {
--    System.arraycopy(elementData, 0, a, 0, elementCount);
-+    System.arraycopy(elementData, 0, anArray, 0, elementCount);
-   }
- 
-   /**
-    * Trims the Vector down to size.  If the internal data array is larger
-    * than the number of Objects its holding, a new array is constructed
--   * that precisely holds the elements. Otherwise this does nothing.
-+   * that precisely holds the elements.  
-    */
-   public synchronized void trimToSize()
-   {
-@@ -182,70 +166,68 @@
-   }
- 
-   /**
--   * Ensures that <code>minCapacity</code> elements can fit within this Vector.
--   * If <code>elementData</code> is too small, it is expanded as follows:
--   * If the <code>elementCount + capacityIncrement</code> is adequate, that
--   * is the new size. If <code>capacityIncrement</code> is non-zero, the
--   * candidate size is double the current. If that is not enough, the new
--   * size is <code>minCapacity</code>.
-+   * Ensures that <b>minCapacity</b> elements can fit within this Vector.
-+   * If it cannot hold this many elements, the internal data array is expanded
-+   * in the following manner.  If the current size plus the capacityIncrement
-+   * is sufficient, the internal array is expanded by capacityIncrement.  
-+   * If capacityIncrement is non-positive, the size is doubled.  If 
-+   * neither is sufficient, the internal array is expanded to size minCapacity
-    *
--   * @param minCapacity the desired minimum capacity, negative values ignored
-+   * @param minCapacity The minimum capacity the internal array should be
-+   * able to handle after executing this method
-    */
-   public synchronized void ensureCapacity(int minCapacity)
-   {
-     if (elementData.length >= minCapacity)
-       return;
- 
--    int newCapacity;
-+    int newCapacity; 
-     if (capacityIncrement <= 0)
-       newCapacity = elementData.length * 2;
-     else
-       newCapacity = elementData.length + capacityIncrement;
--
-+      
-     Object[] newArray = new Object[Math.max(newCapacity, minCapacity)];
- 
--    System.arraycopy(elementData, 0, newArray, 0, elementCount);
-+    System.arraycopy(elementData, 0, newArray, 0, elementData.length);
-     elementData = newArray;
-   }
- 
-   /**
--   * Explicitly sets the size of the vector (but not necessarily the size of
--   * the internal data array). If the new size is smaller than the old one,
--   * old values that don't fit are lost. If the new size is larger than the
--   * old one, the vector is padded with null entries.
-+   * Explicitly sets the size of the internal data array, copying the 
-+   * old values to the new internal array.  If the new array is smaller
-+   * than the old one, old values that don't fit are lost. If the new size
-+   * is larger than the old one, the vector is padded with null entries.
-    *
-    * @param newSize The new size of the internal array
--   * @throws ArrayIndexOutOfBoundsException if the new size is negative
-    */
-   public synchronized void setSize(int newSize)
-   {
--    // Don't bother checking for the case where size() == the capacity of the
--    // vector since that is a much less likely case; it's more efficient to
--    // not do the check and lose a bit of performance in that infrequent case
-     modCount++;
--    ensureCapacity(newSize);
--    if (newSize < elementCount)
--      Arrays.fill(elementData, newSize, elementCount, null);
-+    Object[] newArray = new Object[newSize];
-+    System.arraycopy(elementData, 0, newArray, 0, 
-+                     Math.min(newSize, elementCount));
-     elementCount = newSize;
-+    elementData = newArray;
-   }
- 
-   /**
-    * Returns the size of the internal data array (not the amount of elements
--   * contained in the Vector).
-+   * contained in the Vector)
-    *
--   * @return capacity of the internal data array
-+   * @returns capacity of the internal data array
-    */
--  public synchronized int capacity()
-+  public int capacity()
-   {
-     return elementData.length;
-   }
- 
-   /**
--   * Returns the number of elements stored in this Vector.
-+   * Returns the number of elements stored in this Vector
-    *
--   * @return the number of elements in this Vector
-+   * @returns the number of elements in this Vector
-    */
--  public synchronized int size()
-+  public int size()
-   {
-     return elementCount;
-   }
-@@ -253,89 +235,85 @@
-   /**
-    * Returns true if this Vector is empty, false otherwise
-    *
--   * @return true if the Vector is empty, false otherwise
-+   * @returns true if the Vector is empty, false otherwise
-    */
--  public synchronized boolean isEmpty()
-+  public boolean isEmpty()
-   {
-     return elementCount == 0;
-   }
- 
-   /**
--   * Returns an Enumeration of the elements of this Vector. The enumeration
--   * visits the elements in increasing index order, but is NOT thread-safe.
--   *
--   * @return an Enumeration
--   * @see #iterator()
-+   * Searches the vector starting at <b>index</b> for object <b>elem</b>
-+   * and returns the index of the first occurrence of this Object.  If
-+   * the object is not found, -1 is returned
-+   *
-+   * @param e The Object to search for
-+   * @param index Start searching at this index
-+   * @returns The index of the first occurrence of <b>elem</b>, or -1
-+   * if it is not found
-    */
--  // No need to synchronize as the Enumeration is not thread-safe!
--  public Enumeration elements()
-+  public synchronized int indexOf(Object e, int index)
-   {
--    return new Enumeration()
--    {
--      private int i = 0;
--
--      public boolean hasMoreElements()
--      {
--        return i < elementCount;
--      }
--
--      public Object nextElement()
-+    for (int i = index; i < elementCount; i++)
-       {
--        if (i >= elementCount)
--          throw new NoSuchElementException();
--        return elementData[i++];
-+	if (e == null ? elementData[i] == null : e.equals(elementData[i]))
-+	  return i;
-       }
--    };
-+    return -1;
-   }
- 
-   /**
--   * Returns true when <code>elem</code> is contained in this Vector.
-+   * Returns the first occurrence of <b>elem</b> in the Vector, or -1 if
-+   * <b>elem</b> is not found.
-    *
--   * @param elem the element to check
--   * @return true if the object is contained in this Vector, false otherwise
-+   * @param elem The object to search for
-+   * @returns The index of the first occurrence of <b>elem</b> or -1 if 
-+   * not found
-    */
--  public boolean contains(Object elem)
-+  public int indexOf(Object elem)
-   {
--    return indexOf(elem, 0) >= 0;
-+    return indexOf(elem, 0);
-   }
- 
-   /**
--   * Returns the first occurrence of <code>elem</code> in the Vector, or -1 if
--   * <code>elem</code> is not found.
-+   * Returns true if <b>elem</b> is contained in this Vector, false otherwise.
-    *
--   * @param elem the object to search for
--   * @return the index of the first occurrence, or -1 if not found
-+   * @param elem The element to check
-+   * @returns true if the object is contained in this Vector, false otherwise
-    */
--  public int indexOf(Object elem)
-+  public boolean contains(Object elem)
-   {
--    return indexOf(elem, 0);
-+    return indexOf(elem, 0) != -1;
-   }
- 
-   /**
--   * Searches the vector starting at <code>index</code> for object
--   * <code>elem</code> and returns the index of the first occurrence of this
--   * Object.  If the object is not found, or index is larger than the size
--   * of the vector, -1 is returned.
--   *
--   * @param e the Object to search for
--   * @param index start searching at this index
--   * @return the index of the next occurrence, or -1 if it is not found
--   * @throws IndexOutOfBoundsException if index &lt; 0
-+   * Returns the index of the first occurrence of <b>elem</b>, when searching
-+   * backwards from <b>index</b>.  If the object does not occur in this Vector,
-+   * -1 is returned.
-+   *
-+   * @param eThe object to search for
-+   * @param index The index to start searching in reverse from
-+   * @returns The index of the Object if found, -1 otherwise
-    */
--  public synchronized int indexOf(Object e, int index)
-+  public synchronized int lastIndexOf(Object e, int index)
-   {
--    for (int i = index; i < elementCount; i++)
--      if (equals(e, elementData[i]))
--        return i;
-+    if (index >= elementCount)
-+      throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
-+
-+    for (int i = index; i >= 0; i--)
-+      {
-+	if (e == null ? elementData[i] == null : e.equals(elementData[i]))
-+	  return i;
-+      }
-     return -1;
-   }
- 
-   /**
--   * Returns the last index of <code>elem</code> within this Vector, or -1
--   * if the object is not within the Vector.
-+   * Returns the last index of <b>elem</b> within this Vector, or -1
-+   * if the object is not within the Vector
-    *
--   * @param elem the object to search for
--   * @return the last index of the object, or -1 if not found
-+   * @param elem The object to search for
-+   * @returns the last index of the object, or -1 if not found
-    */
-   public int lastIndexOf(Object elem)
-   {
-@@ -343,42 +321,29 @@
-   }
- 
-   /**
--   * Returns the index of the first occurrence of <code>elem</code>, when
--   * searching backwards from <code>index</code>.  If the object does not
--   * occur in this Vector, or index is less than 0, -1 is returned.
--   *
--   * @param e the object to search for
--   * @param index the index to start searching in reverse from
--   * @return the index of the Object if found, -1 otherwise
--   * @throws IndexOutOfBoundsException if index &gt;= size()
--   */
--  public synchronized int lastIndexOf(Object e, int index)
--  {
--    checkBoundExclusive(index);
--    for (int i = index; i >= 0; i--)
--      if (equals(e, elementData[i]))
--        return i;
--    return -1;
--  }
--
--  /**
--   * Returns the Object stored at <code>index</code>.
-+   * Returns the Object stored at <b>index</b>.  If index is out of range
-+   * an ArrayIndexOutOfBoundsException is thrown.
-    *
-    * @param index the index of the Object to retrieve
--   * @return the object at <code>index</code>
--   * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
--   * @see #get(int)
-+   * @returns The object at <b>index</b>
-+   * @throws ArrayIndexOutOfBoundsException <b>index</b> is
-+   * larger than the Vector
-    */
-   public synchronized Object elementAt(int index)
-   {
--    checkBoundExclusive(index);
-+    //Within the bounds of this Vector does not necessarily mean within 
-+    //the bounds of the internal array
-+    if (index >= elementCount)
-+      throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
-+
-     return elementData[index];
-   }
- 
-   /**
--   * Returns the first element (index 0) in the Vector.
-+   * Returns the first element in the Vector.  If there is no first Object 
-+   * (The vector is empty), a NoSuchElementException is thrown.
-    *
--   * @return the first Object in the Vector
-+   * @returns The first Object in the Vector
-    * @throws NoSuchElementException the Vector is empty
-    */
-   public synchronized Object firstElement()
-@@ -386,13 +351,14 @@
-     if (elementCount == 0)
-       throw new NoSuchElementException();
- 
--    return elementData[0];
-+    return elementAt(0);
-   }
- 
-   /**
--   * Returns the last element in the Vector.
-+   * Returns the last element in the Vector.  If the Vector has no last element
-+   * (The vector is empty), a NoSuchElementException is thrown.
-    *
--   * @return the last Object in the Vector
-+   * @returns The last Object in the Vector
-    * @throws NoSuchElementException the Vector is empty
-    */
-   public synchronized Object lastElement()
-@@ -400,61 +366,95 @@
-     if (elementCount == 0)
-       throw new NoSuchElementException();
- 
--    return elementData[elementCount - 1];
-+    return elementAt(elementCount - 1);
-+  }
-+
-+  /**
-+   * Places <b>obj</b> at <b>index</b> within the Vector.  If <b>index</b>
-+   * refers to an index outside the Vector, an ArrayIndexOutOfBoundsException
-+   * is thrown.  
-+   * 
-+   * @param obj The object to store
-+   * @param index The position in the Vector to store the object
-+   * @throws ArrayIndexOutOfBoundsException the index is out of range
-+   */
-+  public synchronized void setElementAt(Object obj, int index)
-+  {
-+    if (index >= elementCount)
-+      throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
-+
-+    elementData[index] = obj;
-   }
- 
-   /**
--   * Changes the element at <code>index</code> to be <code>obj</code>
-+   * Puts <b>element</b> into the Vector at position <b>index</b> and returns
-+   * the Object that previously occupied that position.
-    *
--   * @param obj the object to store
--   * @param index the position in the Vector to store the object
-+   * @param index The index within the Vector to place the Object
-+   * @param element The Object to store in the Vector
-+   * @returns The previous object at the specified index
-    * @throws ArrayIndexOutOfBoundsException the index is out of range
--   * @see #set(int, Object)
-+   *
-    */
--  public void setElementAt(Object obj, int index)
-+  public synchronized Object set(int index, Object element)
-   {
--    set(index, obj);
-+    if (index >= elementCount)
-+      throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
-+
-+    Object temp = elementData[index];
-+    elementData[index] = element;
-+    return temp;
-   }
- 
-   /**
--   * Removes the element at <code>index</code>, and shifts all elements at
--   * positions greater than index to their index - 1.
-+   * Removes the element at <b>index</b>, and shifts all elements at
-+   * positions greater than index to their index - 1.  
-    *
--   * @param index the index of the element to remove
--   * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size();
--   * @see #remove(int)
-+   * @param index The index of the element to remove
-    */
--  public void removeElementAt(int index)
-+  public synchronized void removeElementAt(int index)
-   {
--    remove(index);
-+    if (index >= elementCount)
-+      throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
-+
-+    modCount++;
-+    elementCount--;
-+    if (index < elementCount)
-+      System.arraycopy(elementData, index + 1, elementData, index,
-+		       elementCount - index);
-+    //Delete the last element (which has been copied back one index)
-+    //so it can be garbage collected;
-+    elementData[elementCount] = null;
-   }
- 
-   /**
--   * Inserts a new element into the Vector at <code>index</code>.  Any elements
-+   * Inserts a new element into the Vector at <b>index</b>.  Any elements
-    * at or greater than index are shifted up one position.
-    *
--   * @param obj the object to insert
--   * @param index the index at which the object is inserted
--   * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
--   * @see #add(int, Object)
-+   * @param obj The object to insert
-+   * @param index The index at which the object is inserted
-    */
--  public synchronized void insertElementAt(Object obj, int index)
-+  public void insertElementAt(Object obj, int index)
-   {
--    checkBoundInclusive(index);
-+    if (index > elementCount)
-+      throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount);
-+
-     if (elementCount == elementData.length)
-       ensureCapacity(elementCount + 1);
--    modCount++;
-+    ++modCount;
-+    ++elementCount;
-     System.arraycopy(elementData, index, elementData, index + 1,
--                     elementCount - index);
--    elementCount++;
-+		     elementCount - 1 - index);
-     elementData[index] = obj;
-   }
- 
-   /**
--   * Adds an element to the Vector at the end of the Vector.  The vector
--   * is increased by ensureCapacity(size() + 1) if needed.
-+   * Adds an element to the Vector at the end of the Vector.  If the vector
-+   * cannot hold the element with its present capacity, its size is increased
-+   * based on the same rules followed if ensureCapacity was called with the
-+   * argument currentSize+1.
-    *
--   * @param obj the object to add to the Vector
-+   * @param obj The object to add to the Vector
-    */
-   public synchronized void addElement(Object obj)
-   {
-@@ -465,21 +465,20 @@
-   }
- 
-   /**
--   * Removes the first (the lowestindex) occurance of the given object from
--   * the Vector. If such a remove was performed (the object was found), true
--   * is returned. If there was no such object, false is returned.
--   *
--   * @param obj the object to remove from the Vector
--   * @return true if the Object was in the Vector, false otherwise
--   * @see #remove(Object)
-+   * Removes the first occurrence of the given object from the Vector.
-+   * If such a remove was performed (the object was found), true is returned.
-+   * If there was no such object, false is returned.
-+   *
-+   * @param obj The object to remove from the Vector
-+   * @returns true if the Object was in the Vector, false otherwise
-    */
-   public synchronized boolean removeElement(Object obj)
-   {
--    int idx = indexOf(obj, 0);
--    if (idx >= 0)
-+    int idx = indexOf(obj);
-+    if (idx != -1)
-       {
--        remove(idx);
--        return true;
-+	removeElementAt(idx);
-+	return true;
-       }
-     return false;
-   }
-@@ -487,49 +486,46 @@
-   /**
-    * Removes all elements from the Vector.  Note that this does not
-    * resize the internal data array.
--   *
--   * @see #clear()
-    */
-   public synchronized void removeAllElements()
-   {
-+    modCount++;
-     if (elementCount == 0)
-       return;
- 
--    modCount++;
--    Arrays.fill(elementData, 0, elementCount, null);
-+    for (int i = elementCount - 1; i >= 0; --i)
-+      {
-+	elementData[i] = null;
-+      }
-     elementCount = 0;
-   }
- 
-   /**
--   * Creates a new Vector with the same contents as this one. The clone is
--   * shallow; elements are not cloned.
--   *
--   * @return the clone of this vector
-+   * Creates a new Vector with the same contents as this one.
-    */
-   public synchronized Object clone()
-   {
-     try
-       {
--        Vector clone = (Vector) super.clone();
--        clone.elementData = (Object[]) elementData.clone();
--        return clone;
-+	Vector clone = (Vector) super.clone();
-+	clone.elementData = (Object[]) elementData.clone();
-+	return clone;
-       }
-     catch (CloneNotSupportedException ex)
-       {
--        // Impossible to get here.
--        throw new InternalError(ex.toString());
-+	throw new InternalError(ex.toString());
-       }
-   }
- 
-   /**
-    * Returns an Object array with the contents of this Vector, in the order
--   * they are stored within this Vector.  Note that the Object array returned
--   * is not the internal data array, and that it holds only the elements
--   * within the Vector.  This is similar to creating a new Object[] with the
-+   * they are stored within this Vector.  Note that the Object array returned 
-+   * is not the internal data array, and that it holds only the elements 
-+   * within the Vector.  This is similar to creating a new Object[] with the 
-    * size of this Vector, then calling Vector.copyInto(yourArray).
-    *
--   * @return an Object[] containing the contents of this Vector in order
--   * @since 1.2
-+   * @returns An Object[] containing the contents of this Vector in order
-+   *
-    */
-   public synchronized Object[] toArray()
-   {
-@@ -539,97 +535,76 @@
-   }
- 
-   /**
--   * Returns an array containing the contents of this Vector.
-+   * Returns an array containing the contents of this Vector.  
-    * If the provided array is large enough, the contents are copied
--   * into that array, and a null is placed in the position size().
-+   * into that array, and a null is placed in the position size(). 
-    * In this manner, you can obtain the size of a Vector by the position
--   * of the null element, if you know the vector does not itself contain
--   * null entries.  If the array is not large enough, reflection is used
--   * to create a bigger one of the same runtime type.
-+   * of the null element.  If the type of the provided array cannot 
-+   * hold the elements, an ArrayStoreException is thrown.
-+   * 
-+   * If the provided array is not large enough,
-+   * a new one is created with the contents of the Vector, and no null 
-+   * element.  The new array is of the same runtime type as the provided
-+   * array.
-+   *
-    *
--   * @param a an array to copy the Vector into if large enough
--   * @return an array with the contents of this Vector in order
-+   * @param array An array to copy the Vector into if large enough
-+   * @returns An array with the contents of this Vector in order
-    * @throws ArrayStoreException the runtime type of the provided array
--   *         cannot hold the elements of the Vector
--   * @throws NullPointerException if <code>a</code> is null
--   * @since 1.2
-+   * cannot hold the elements of the Vector
-    */
--  public synchronized Object[] toArray(Object[] a)
-+  public synchronized Object[] toArray(Object[] array)
-   {
--    if (a.length < elementCount)
--      a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
--                                       elementCount);
--    else if (a.length > elementCount)
--      a[elementCount] = null;
--    System.arraycopy(elementData, 0, a, 0, elementCount);
--    return a;
-+    if (array.length < elementCount)
-+      array = (Object[]) Array.newInstance(array.getClass().getComponentType(), 
-+        				   elementCount);
-+    else if (array.length > elementCount)
-+      array[elementCount] = null;
-+    System.arraycopy(elementData, 0, array, 0, elementCount);
-+    return array;
-   }
- 
-   /**
--   * Returns the element at position <code>index</code>.
-+   * Returns the element at position <b>index</b>
-    *
-    * @param index the position from which an element will be retrieved
--   * @return the element at that position
--   * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
--   * @since 1.2
-+   * @throws ArrayIndexOutOfBoundsException the index is not within the 
-+   * range of the Vector
-    */
--  public Object get(int index)
-+  public synchronized Object get(int index)
-   {
-     return elementAt(index);
-   }
- 
-   /**
--   * Puts <code>element</code> into the Vector at position <code>index</code>
--   * and returns the Object that previously occupied that position.
-+   * Removes the given Object from the Vector.  If it exists, true
-+   * is returned, if not, false is returned.
-    *
--   * @param index the index within the Vector to place the Object
--   * @param element the Object to store in the Vector
--   * @return the previous object at the specified index
--   * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
--   * @since 1.2
-+   * @param o The object to remove from the Vector
-+   * @returns true if the Object existed in the Vector, false otherwise
-    */
--  public synchronized Object set(int index, Object element)
-+  public boolean remove(Object o)
-   {
--    checkBoundExclusive(index);
--    Object temp = elementData[index];
--    elementData[index] = element;
--    return temp;
-+    return removeElement(o);
-   }
- 
-   /**
-    * Adds an object to the Vector.
-    *
--   * @param o the element to add to the Vector
--   * @return true, as specified by List
--   * @since 1.2
-+   * @param o The element to add to the Vector
-    */
--  public boolean add(Object o)
-+  public synchronized boolean add(Object o)
-   {
-     addElement(o);
-     return true;
-   }
- 
-   /**
--   * Removes the given Object from the Vector.  If it exists, true
--   * is returned, if not, false is returned.
--   *
--   * @param o the object to remove from the Vector
--   * @return true if the Object existed in the Vector, false otherwise
--   * @since 1.2
--   */
--  public boolean remove(Object o)
--  {
--    return removeElement(o);
--  }
--
--  /**
-    * Adds an object at the specified index.  Elements at or above
-    * index are shifted up one position.
-    *
--   * @param index the index at which to add the element
--   * @param element the element to add to the Vector
--   * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
--   * @since 1.2
-+   * @param index The index at which to add the element
-+   * @param element The element to add to the Vector
-    */
-   public void add(int index, Object element)
-   {
-@@ -639,253 +614,153 @@
-   /**
-    * Removes the element at the specified index, and returns it.
-    *
--   * @param index the position from which to remove the element
--   * @return the object removed
--   * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
--   * @since 1.2
-+   * @param index The position from which to remove the element
-+   * @returns The object removed
-+   * @throws ArrayIndexOutOfBoundsException the index was out of the range
-+   * of the Vector
-    */
-   public synchronized Object remove(int index)
-   {
--    checkBoundExclusive(index);
-+    if (index >= elementCount)
-+      throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
-+  
-     Object temp = elementData[index];
--    modCount++;
--    elementCount--;
--    if (index < elementCount)
--      System.arraycopy(elementData, index + 1, elementData, index,
--                       elementCount - index);
--    elementData[elementCount] = null;
-+    removeElementAt(index);
-     return temp;
-   }
- 
-   /**
--   * Clears all elements in the Vector and sets its size to 0.
-+   * Clears all elements in the Vector and sets its size to 0
-    */
-   public void clear()
-   {
-     removeAllElements();
-   }
- 
--  /**
--   * Returns true if this Vector contains all the elements in c.
--   *
--   * @param c the collection to compare to
--   * @return true if this vector contains all elements of c
--   * @throws NullPointerException if c is null
--   * @since 1.2
--   */
-   public synchronized boolean containsAll(Collection c)
-   {
--    // Here just for the sychronization.
--    return super.containsAll(c);
-+    Iterator itr = c.iterator();
-+    int size = c.size();
-+    for (int pos = 0; pos < size; pos++)
-+      {
-+	if (!contains(itr.next()))
-+	  return false;
-+      }
-+    return true;
-   }
- 
--  /**
--   * Appends all elements of the given collection to the end of this Vector.
--   * Behavior is undefined if the collection is modified during this operation
--   * (for example, if this == c).
--   *
--   * @param c the collection to append
--   * @return true if this vector changed, in other words c was not empty
--   * @throws NullPointerException if c is null
--   * @since 1.2
--   */
-   public synchronized boolean addAll(Collection c)
-   {
-     return addAll(elementCount, c);
-   }
--
--  /**
--   * Remove from this vector all elements contained in the given collection.
--   *
--   * @param c the collection to filter out
--   * @return true if this vector changed
--   * @throws NullPointerException if c is null
--   * @since 1.2
--   */
-+  
-   public synchronized boolean removeAll(Collection c)
-   {
--    int i;
--    int j;
--    for (i = 0; i < elementCount; i++)
--      if (c.contains(elementData[i]))
--        break;
--    if (i == elementCount)
--      return false;
--
--    modCount++;
--    for (j = i++; i < elementCount; i++)
--      if (! c.contains(elementData[i]))
--        elementData[j++] = elementData[i];
--    elementCount -= i - j;
--    return true;
-+    return super.removeAll(c);
-   }
--
--  /**
--   * Retain in this vector only the elements contained in the given collection.
--   *
--   * @param c the collection to filter by
--   * @return true if this vector changed
--   * @throws NullPointerException if c is null
--   * @since 1.2
--   */
-+  
-   public synchronized boolean retainAll(Collection c)
-   {
--    int i;
--    int j;
--    for (i = 0; i < elementCount; i++)
--      if (! c.contains(elementData[i]))
--        break;
--    if (i == elementCount)
--      return false;
--
--    modCount++;
--    for (j = i++; i < elementCount; i++)
--      if (c.contains(elementData[i]))
--        elementData[j++] = elementData[i];
--    elementCount -= i - j;
--    return true;
-+    return super.retainAll(c);
-   }
- 
--  /**
--   * Inserts all elements of the given collection at the given index of
--   * this Vector. Behavior is undefined if the collection is modified during
--   * this operation (for example, if this == c).
--   *
--   * @param c the collection to append
--   * @return true if this vector changed, in other words c was not empty
--   * @throws NullPointerException if c is null
--   * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
--   * @since 1.2
--   */
-   public synchronized boolean addAll(int index, Collection c)
-   {
--    checkBoundInclusive(index);
-+    if (index < 0 || index > elementCount)
-+      throw new ArrayIndexOutOfBoundsException(index);
-+    modCount++;
-     Iterator itr = c.iterator();
-     int csize = c.size();
- 
--    modCount++;
-     ensureCapacity(elementCount + csize);
-     int end = index + csize;
-     if (elementCount > 0 && index != elementCount)
-       System.arraycopy(elementData, index, elementData, end, csize);
-     elementCount += csize;
--    for ( ; index < end; index++)
--      elementData[index] = itr.next();
--    return (csize > 0);
-+    for (; index < end; index++)
-+      {
-+        elementData[index] = itr.next();
-+      }
-+    return (csize > 0);  
-   }
- 
--  /**
--   * Compares this to the given object.
--   *
--   * @param o the object to compare to
--   * @return true if the two are equal
--   * @since 1.2
--   */
--  public synchronized boolean equals(Object o)
-+  public synchronized boolean equals(Object c)
-   {
--    // Here just for the sychronization.
--    return super.equals(o);
-+    return super.equals(c);
-   }
- 
--  /**
--   * Computes the hashcode of this object.
--   *
--   * @return the hashcode
--   * @since 1.2
--   */
-   public synchronized int hashCode()
-   {
--    // Here just for the sychronization.
-     return super.hashCode();
-   }
- 
-   /**
--   * Returns a string representation of this Vector in the form
--   * "[element0, element1, ... elementN]".
-+   * Returns a string representation of this Vector in the form 
-+   * [element0, element1, ... elementN]
-    *
--   * @return the String representation of this Vector
-+   * @returns the String representation of this Vector
-    */
-   public synchronized String toString()
-   {
--    // Here just for the sychronization.
--    return super.toString();
--  }
--
--  /**
--   * Obtain a List view of a subsection of this list, from fromIndex
--   * (inclusive) to toIndex (exclusive). If the two indices are equal, the
--   * sublist is empty. The returned list is modifiable, and changes in one
--   * reflect in the other. If this list is structurally modified in
--   * any way other than through the returned list, the result of any subsequent
--   * operations on the returned list is undefined.
--   * <p>
--   *
--   * @param fromIndex the index that the returned list should start from
--   *        (inclusive)
--   * @param toIndex the index that the returned list should go to (exclusive)
--   * @return a List backed by a subsection of this vector
--   * @throws IndexOutOfBoundsException if fromIndex &lt; 0
--   *         || toIndex &gt; size()
--   * @throws IllegalArgumentException if fromIndex &gt; toIndex
--   * @see ConcurrentModificationException
--   * @since 1.2
--   */
--  public synchronized List subList(int fromIndex, int toIndex)
--  {
--    List sub = super.subList(fromIndex, toIndex);
--    // We must specify the correct object to synchronize upon, hence the
--    // use of a non-public API
--    return new Collections.SynchronizedList(this, sub);
-+    String r = "[";
-+    for (int i = 0; i < elementCount; i++)
-+      {
-+	r += elementData[i];
-+	if (i < elementCount - 1)
-+	  r += ", ";
-+      }
-+    r += "]";
-+    return r;
-   }
- 
-   /**
--   * Removes a range of elements from this list.
-+   * Returns an Enumeration of the elements of this List.
-+   * The Enumeration returned is compatible behavior-wise with
-+   * the 1.1 elements() method, in that it does not check for
-+   * concurrent modification.
-    *
--   * @param fromIndex the index to start deleting from (inclusive)
--   * @param toIndex the index to delete up to (exclusive)
-+   * @returns an Enumeration
-    */
--  // This does not need to be synchronized, because it is only called through
--  // clear() of a sublist, and clear() had already synchronized.
--  protected void removeRange(int fromIndex, int toIndex)
-+  public synchronized Enumeration elements()
-   {
--    if (fromIndex != toIndex)
-+    return new Enumeration()
-+    {
-+      int i = 0;
-+      public boolean hasMoreElements()
-+      {
-+	return (i < elementCount);
-+      }
-+      public Object nextElement()
-       {
--        modCount++;
--        System.arraycopy(elementData, toIndex, elementData, fromIndex,
--                         elementCount - toIndex);
--        int save = elementCount;
--        elementCount -= toIndex - fromIndex;
--        Arrays.fill(elementData, elementCount, save, null);
-+	if (i >= elementCount)
-+	  throw new NoSuchElementException();
-+	return (elementAt(i++));
-       }
-+    };
-   }
--
--  /**
--   * Checks that the index is in the range of possible elements (inclusive).
--   *
--   * @param index the index to check
--   * @throws ArrayIndexOutOfBoundsException if index &gt; size
--   */
--  private void checkBoundInclusive(int index)
-+  
-+  public List subList(int fromIndex, int toIndex)
-   {
--    // Implementation note: we do not check for negative ranges here, since
--    // use of a negative index will cause an ArrayIndexOutOfBoundsException
--    // with no effort on our part.
--    if (index > elementCount)
--      throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount);
-+    List sub = super.subList(fromIndex, toIndex);
-+    return Collections.synchronizedList(sub);
-   }
--
--  /**
--   * Checks that the index is in the range of existing elements (exclusive).
--   *
--   * @param index the index to check
--   * @throws ArrayIndexOutOfBoundsException if index &gt;= size
--   */
--  private void checkBoundExclusive(int index)
-+  
-+  /** @specnote This is not specified as synchronized in the JCL, but it seems
-+    * to me that is should be. If it isn't, a clear() operation on a sublist
-+    * will not be synchronized w.r.t. the Vector object.
-+    */
-+  protected synchronized void removeRange(int fromIndex, int toIndex)
-   {
--    // Implementation note: we do not check for negative ranges here, since
--    // use of a negative index will cause an ArrayIndexOutOfBoundsException
--    // with no effort on our part.
--    if (index >= elementCount)
--      throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
-+    modCount++;
-+    if (fromIndex != toIndex)
-+      {
-+	System.arraycopy(elementData, toIndex, elementData, fromIndex, 
-+	                 elementCount - toIndex);
-+	// Clear unused elements so objects can be collected.
-+	int save = elementCount;
-+	elementCount -= (toIndex - fromIndex);
-+	for (int i = elementCount; i < save; ++i)
-+	  elementData[i] = null;
-+      }
-   }
- }
++ * @author Bryce McKinlay
+  * @author Eric Blake <ebb9@email.byu.edu>
+  * @see Collection
+  * @see List


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]