This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Patch: FYI: libgcj / classpath comparison
- From: Tom Tromey <tromey at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Cc: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Date: 15 Dec 2001 17:22:25 -0700
- Subject: Patch: FYI: libgcj / classpath comparison
- Reply-to: tromey at redhat dot com
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 < 0 || index > 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 < 0 || index > 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 < 0 || index > 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 < 0 || index >= 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 < 0 || index >= 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 < 0 || index >= 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 < 0 || index >= 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 < 0 || index >= 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 < 0 || index > 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 < 0 || index >= 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 < 0 || index > 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 > 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 >= 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 < 0, 0, or > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 < 0, 0, or > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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 > toIndex
-- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-- * || toIndex > 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() > 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() > 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 < 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 < 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 <, ==, or > 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 < 0 or >=
-- * 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 < 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 >= 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 > 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 <= 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 < 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 < 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 < 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 >= 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 < 0 || index >= 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 < 0 || index >= 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 < 0 || index > 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 < 0 || index >= 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 < 0 || index >= 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 < 0 || index > 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 < 0 || index >= 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 < 0 || index > 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 < 0
-- * || toIndex > size()
-- * @throws IllegalArgumentException if fromIndex > 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 > 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 >= 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