aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/util/Collections.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/util/Collections.java')
-rw-r--r--libjava/java/util/Collections.java1829
1 files changed, 1829 insertions, 0 deletions
diff --git a/libjava/java/util/Collections.java b/libjava/java/util/Collections.java
new file mode 100644
index 0000000..a827071
--- /dev/null
+++ b/libjava/java/util/Collections.java
@@ -0,0 +1,1829 @@
+/* Collections.java -- Utility class with methods to operate on collections
+ Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+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;
+
+/**
+ * Utility class consisting of static methods that operate on, or return
+ * Collections. Contains methods to sort, search, reverse, fill and shuffle
+ * Collections, methods to facilitate interoperability with legacy APIs that
+ * 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.
+ */
+public class Collections
+{
+
+ /**
+ * This class is non-instantiable.
+ */
+ private Collections()
+ {
+ }
+
+ /**
+ * An immutable, empty Set.
+ * Note: This implementation isn't Serializable, although it should be by the
+ * spec.
+ */
+ public static final Set EMPTY_SET = new AbstractSet()
+ {
+
+ public int size()
+ {
+ return 0;
+ }
+
+ // 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();
+ }
+
+ // 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.
+ */
+ public static final List EMPTY_LIST = new AbstractList()
+ {
+
+ public int size()
+ {
+ return 0;
+ }
+
+ public Object get(int index)
+ {
+ throw new IndexOutOfBoundsException();
+ }
+ };
+
+ /**
+ * An immutable, empty Map.
+ * Note: This implementation isn't serializable, although it should be by the
+ * spec.
+ */
+ public static final Map EMPTY_MAP = new AbstractMap()
+ {
+
+ public Set entrySet()
+ {
+ return EMPTY_SET;
+ }
+ };
+
+ /**
+ * 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 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.
+ */
+ private static int search(List l, Object key, final Comparator c)
+ {
+
+ 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 i = l.listIterator();
+ while (i.hasNext())
+ {
+ final int d = compare(key, i.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 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. 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
+ * @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 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 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. 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
+ * @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)
+ {
+ if (c == null)
+ {
+ throw new NullPointerException();
+ }
+ return search(l, key, c);
+ }
+
+ /**
+ * Copy one list to another. If the destination list is longer than the
+ * source list, the remaining elements are unaffected. This method runs in
+ * linear time.
+ *
+ * @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)
+ {
+ Iterator i1 = source.iterator();
+ ListIterator i2 = dest.listIterator();
+ while (i1.hasNext())
+ {
+ i2.next();
+ i2.set(i1.next());
+ }
+ }
+
+ /**
+ * Returns an Enumeration over a collection. This allows interoperability
+ * with legacy APIs that require an Enumeration as input.
+ *
+ * @param c the Collection to iterate over
+ * @returns an Enumeration backed by an Iterator over c
+ */
+ public static Enumeration enumeration(Collection c)
+ {
+ final Iterator i = c.iterator();
+ return new Enumeration()
+ {
+ public final boolean hasMoreElements()
+ {
+ return i.hasNext();
+ }
+ public final Object nextElement()
+ {
+ return i.next();
+ }
+ };
+ }
+
+ /**
+ * Replace every element of a list with a given value. This method runs in
+ * linear time.
+ *
+ * @param l the list to fill.
+ * @param val the object to vill the list with.
+ * @exception UnsupportedOperationException if l.listIterator() does not
+ * support the set operation.
+ */
+ public static void fill(List l, Object val)
+ {
+ ListIterator i = l.listIterator();
+ while (i.hasNext())
+ {
+ i.next();
+ i.set(val);
+ }
+ }
+
+ /**
+ * 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
+ * @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)
+ {
+ Iterator i = c.iterator();
+ Comparable max = (Comparable) i.next(); // throws NoSuchElementException
+ while (i.hasNext())
+ {
+ Object o = i.next();
+ if (max.compareTo(o) < 0)
+ {
+ max = (Comparable) o;
+ }
+ }
+ return max;
+ }
+
+ /**
+ * Find the maximum element in a Collection, according to a specified
+ * Comparator. This implementation iterates over the Collection, so it
+ * works in linear time.
+ *
+ * @param c the Collection to find the maximum element of
+ * @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 i = c.iterator();
+ Object max = i.next(); // throws NoSuchElementException
+ while (i.hasNext())
+ {
+ Object o = i.next();
+ if (order.compare(max, o) < 0)
+ {
+ max = o;
+ }
+ }
+ return max;
+ }
+
+ /**
+ * Find the minimum 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 minimum element of
+ * @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)
+ {
+ Iterator i = c.iterator();
+ Comparable min = (Comparable) i.next(); // throws NoSuchElementException
+ while (i.hasNext())
+ {
+ Object o = i.next();
+ if (min.compareTo(o) > 0)
+ {
+ min = (Comparable) o;
+ }
+ }
+ return min;
+ }
+
+ /**
+ * Find the minimum element in a Collection, according to a specified
+ * Comparator. This implementation iterates over the Collection, so it
+ * works in linear time.
+ *
+ * @param c the Collection to find the minimum element of
+ * @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)
+ {
+ Iterator i = c.iterator();
+ Object min = i.next(); // throws NoSuchElementExcception
+ while (i.hasNext())
+ {
+ Object o = i.next();
+ if (order.compare(min, o) > 0)
+ {
+ min = o;
+ }
+ }
+ return min;
+ }
+
+ /**
+ * 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.
+ *
+ * @param n the number of times to repeat the object
+ * @param o the object to repeat
+ * @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)
+ {
+
+ // Check for insane arguments
+ if (n < 0)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ // Create a minimal implementation of List
+ return new AbstractList()
+ {
+
+ public int size()
+ {
+ return n;
+ }
+
+ public Object get(int index)
+ {
+ if (index < 0 || index >= n)
+ {
+ throw new IndexOutOfBoundsException();
+ }
+ return o;
+ }
+ };
+ }
+
+ /**
+ * Reverse a given list. This method works in linear time.
+ *
+ * @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();
+ ListIterator i2 = l.listIterator(l.size());
+ while (i1.nextIndex() < i2.previousIndex())
+ {
+ Object o = i1.next();
+ i1.set(i2.previous());
+ i2.set(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.
+ */
+ // The return value isn't Serializable, because the spec is broken.
+ public static Comparator reverseOrder()
+ {
+ return new Comparator()
+ {
+ public int compare(Object a, Object b)
+ {
+ return -((Comparable) a).compareTo(b);
+ }
+ };
+ }
+
+ /**
+ * Shuffle a list according to a default source of randomness. The algorithm
+ * 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 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)
+ {
+ shuffle(l, new Random());
+ }
+
+ /**
+ * Shuffle a list according to a given 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 practise (eg if r = new Random()) the
+ * results are merely very close to perfect.
+ * <p>
+ * 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
+ ListIterator i = l.listIterator(l.size());
+
+ // Iterate backwards over l
+ while (i.hasPrevious())
+ {
+
+ // Obtain a random position to swap with. nextIndex is used so that the
+ // range of the random number includes the current position.
+ int swap = r.nextInt(i.nextIndex());
+
+ // Swap the swapth element of the array with the next element of the
+ // list.
+ Object o = a[swap];
+ a[swap] = a[i.previousIndex()];
+ a[i.previousIndex()] = 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.
+ * @returns an immutable Set containing only o.
+ */
+ // It's not serializable because the spec is broken.
+ public static Set singleton(final Object o)
+ {
+
+ return new AbstractSet()
+ {
+
+ public int size()
+ {
+ return 1;
+ }
+
+ public Iterator iterator()
+ {
+ return new Iterator()
+ {
+
+ private boolean hasNext = true;
+
+ public boolean hasNext()
+ {
+ return hasNext;
+ }
+
+ public Object next()
+ {
+ if (hasNext)
+ {
+ hasNext = false;
+ return o;
+ }
+ else
+ {
+ throw new NoSuchElementException();
+ }
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ };
+ }
+
+ /**
+ * Obtain an immutable List consisting of a single element. The return value
+ * of this method is Serializable.
+ *
+ * @param o the single element.
+ * @returns an immutable List containing only o.
+ */
+ // It's not serializable because the spec is broken.
+ public static List singletonList(final Object o)
+ {
+
+ return new AbstractList()
+ {
+
+ public int size()
+ {
+ return 1;
+ }
+
+ public Object get(int index)
+ {
+ if (index == 0)
+ {
+ throw new IndexOutOfBoundsException();
+ }
+ else
+ {
+ return o;
+ }
+ }
+ };
+ }
+
+ /**
+ * 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.
+ * @returns an immutable Map containing only the single key value pair.
+ */
+ // It's not serializable because the spec is broken.
+ public static Map singletonMap(final Object key, final Object value)
+ {
+
+ return new AbstractMap()
+ {
+ public Set entrySet()
+ {
+ return singleton(new BasicMapEntry(key, value));
+ }
+ };
+ }
+
+ /**
+ * Sort a list according to the natural ordering of its elements. The list
+ * must be modifiable, but can be of fixed size. The sort algorithm is
+ * precisely that used by Arrays.sort(Object[]), which offers guaranteed
+ * nlog(n) performance. This implementation dumps the list into an array,
+ * sorts the array, and then iterates over the list setting each element from
+ * the array.
+ *
+ * @param l the List to sort
+ * @exception ClassCastException if some items are not mutually comparable
+ * @exception UnsupportedOperationException if the List is not modifiable
+ */
+ public static void sort(List l)
+ {
+ 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]);
+ }
+ }
+
+ /**
+ * Sort a list according to a specified Comparator. The list must be
+ * modifiable, but can be of fixed size. The sort algorithm is precisely that
+ * used by Arrays.sort(Object[], Comparator), which offers guaranteed
+ * nlog(n) performance. This implementation dumps the list into an array,
+ * sorts the array, and then iterates over the list setting each element from
+ * the array.
+ *
+ * @param l the List to sort
+ * @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();
+ for (int pos = 0; pos < a.length; pos++)
+ {
+ i.next();
+ i.set(a[pos]);
+ }
+ }
+
+ // 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);
+ }
+
+ // 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
+ {
+ private Iterator i;
+
+ public UnmodifiableIterator(Iterator i)
+ {
+ this.i = i;
+ }
+
+ public Object next()
+ {
+ return i.next();
+ }
+ public boolean hasNext()
+ {
+ return i.hasNext();
+ }
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ 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)
+ {
+ super(li);
+ this.li = li;
+ }
+
+ 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)
+ {
+ throw new UnsupportedOperationException();
+ }
+ public void set(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private static class UnmodifiableCollection implements Collection,
+ Serializable
+ {
+ Collection c;
+
+ public UnmodifiableCollection(Collection c)
+ {
+ 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)
+ {
+ return c.contains(o);
+ }
+ public boolean containsAll(Collection c1)
+ {
+ return c.containsAll(c1);
+ }
+ public boolean isEmpty()
+ {
+ return c.isEmpty();
+ }
+ public Iterator iterator()
+ {
+ return new UnmodifiableIterator(c.iterator());
+ }
+ public boolean remove(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+ public boolean removeAll(Collection c)
+ {
+ throw new UnsupportedOperationException();
+ }
+ public boolean retainAll(Collection c)
+ {
+ throw new UnsupportedOperationException();
+ }
+ public int size()
+ {
+ return c.size();
+ }
+ public Object[] toArray()
+ {
+ return c.toArray();
+ }
+ public Object[] toArray(Object[]a)
+ {
+ return c.toArray(a);
+ }
+ }
+
+ private static class UnmodifiableList extends UnmodifiableCollection
+ implements List
+ {
+
+ // This is stored both here and in the superclass, to avoid excessive
+ // casting.
+ List l;
+
+ public UnmodifiableList(List l)
+ {
+ super(l);
+ this.l = l;
+ }
+
+ public void add(int index, Object o)
+ {
+ l.add(index, o);
+ }
+ public boolean addAll(int index, Collection c)
+ {
+ return l.addAll(index, c);
+ }
+ public boolean equals(Object o)
+ {
+ return l.equals(o);
+ }
+ public Object get(int index)
+ {
+ return l.get(index);
+ }
+ public int hashCode()
+ {
+ return l.hashCode();
+ }
+ public int indexOf(Object o)
+ {
+ return l.indexOf(o);
+ }
+ public int lastIndexOf(Object o)
+ {
+ return l.lastIndexOf(o);
+ }
+ public ListIterator listIterator()
+ {
+ return new UnmodifiableListIterator(l.listIterator());
+ }
+ public ListIterator listIterator(int index)
+ {
+ return new UnmodifiableListIterator(l.listIterator(index));
+ }
+ public Object remove(int index)
+ {
+ return l.remove(index);
+ }
+ public boolean remove(Object o)
+ {
+ return l.remove(o);
+ }
+ public Object set(int index, Object o)
+ {
+ return l.set(index, o);
+ }
+ public List subList(int fromIndex, int toIndex)
+ {
+ return new UnmodifiableList(l.subList(fromIndex, toIndex));
+ }
+ }
+
+ private static class UnmodifiableSet extends UnmodifiableCollection
+ implements Set
+ {
+ public UnmodifiableSet(Set s)
+ {
+ super(s);
+ }
+ public boolean equals(Object o)
+ {
+ return c.equals(o);
+ }
+ public int hashCode()
+ {
+ return c.hashCode();
+ }
+ }
+
+ private static class UnmodifiableSortedSet extends UnmodifiableSet
+ implements SortedSet
+ {
+
+ // This is stored both here and in the superclass, to avoid excessive
+ // casting.
+ private SortedSet ss;
+
+ public UnmodifiableSortedSet(SortedSet ss)
+ {
+ super(ss);
+ this.ss = ss;
+ }
+
+ public Comparator comparator()
+ {
+ return ss.comparator();
+ }
+ public Object first()
+ {
+ return ss.first();
+ }
+ public Object last()
+ {
+ return ss.last();
+ }
+ public SortedSet headSet(Object toElement)
+ {
+ return new UnmodifiableSortedSet(ss.headSet(toElement));
+ }
+ public SortedSet tailSet(Object fromElement)
+ {
+ return new UnmodifiableSortedSet(ss.tailSet(fromElement));
+ }
+ public SortedSet subSet(Object fromElement, Object toElement)
+ {
+ return new UnmodifiableSortedSet(ss.subSet(fromElement, toElement));
+ }
+ }
+
+ private static class UnmodifiableMap implements Map, Serializable
+ {
+
+ Map m;
+
+ public UnmodifiableMap(Map m)
+ {
+ this.m = m;
+ }
+
+ public void clear()
+ {
+ throw new UnsupportedOperationException();
+ }
+ public boolean containsKey(Object key)
+ {
+ return m.containsKey(key);
+ }
+ public boolean containsValue(Object value)
+ {
+ return m.containsValue(value);
+ }
+
+ // This is one of the ickiest cases of nesting I've ever seen. It just
+ // 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()
+ {
+ return new UnmodifiableSet(m.entrySet())
+ {
+ 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)
+ {
+ return m.equals(o);
+ }
+ public Object get(Object key)
+ {
+ return m.get(key);
+ }
+ public Object put(Object key, Object value)
+ {
+ throw new UnsupportedOperationException();
+ }
+ public int hashCode()
+ {
+ return m.hashCode();
+ }
+ public boolean isEmpty()
+ {
+ return m.isEmpty();
+ }
+ public Set keySet()
+ {
+ return new UnmodifiableSet(m.keySet());
+ }
+ public void putAll(Map m)
+ {
+ throw new UnsupportedOperationException();
+ }
+ public Object remove(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+ public int size()
+ {
+ return m.size();
+ }
+ public Collection values()
+ {
+ return new UnmodifiableCollection(m.values());
+ }
+ }
+
+ private static class UnmodifiableSortedMap extends UnmodifiableMap
+ implements SortedMap
+ {
+
+ // This is stored both here and in the superclass, to avoid excessive
+ // casting.
+ private SortedMap sm;
+
+ public UnmodifiableSortedMap(SortedMap sm)
+ {
+ super(sm);
+ this.sm = sm;
+ }
+
+ public Comparator comparator()
+ {
+ return sm.comparator();
+ }
+ public Object firstKey()
+ {
+ return sm.firstKey();
+ }
+ public Object lastKey()
+ {
+ return sm.lastKey();
+ }
+ public SortedMap headMap(Object toKey)
+ {
+ return new UnmodifiableSortedMap(sm.headMap(toKey));
+ }
+ public SortedMap tailMap(Object fromKey)
+ {
+ return new UnmodifiableSortedMap(sm.tailMap(fromKey));
+ }
+ public SortedMap subMap(Object fromKey, Object toKey)
+ {
+ return new UnmodifiableSortedMap(sm.subMap(fromKey, toKey));
+ }
+ }
+
+ // 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
+ {
+ Object sync;
+ private Iterator i;
+
+ public SynchronizedIterator(Object sync, Iterator i)
+ {
+ this.sync = sync;
+ this.i = i;
+ }
+
+ public Object next()
+ {
+ synchronized(sync)
+ {
+ return i.next();
+ }
+ }
+ public boolean hasNext()
+ {
+ synchronized(sync)
+ {
+ return i.hasNext();
+ }
+ }
+ public void remove()
+ {
+ synchronized(sync)
+ {
+ i.remove();
+ }
+ }
+ }
+
+ 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)
+ {
+ super(sync, li);
+ this.li = li;
+ }
+
+ public boolean hasPrevious()
+ {
+ synchronized(sync)
+ {
+ return li.hasPrevious();
+ }
+ }
+ public Object previous()
+ {
+ synchronized(sync)
+ {
+ return li.previous();
+ }
+ }
+ public int nextIndex()
+ {
+ 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);
+ }
+ }
+ }
+
+ private static class SynchronizedCollection implements Collection,
+ Serializable
+ {
+ Object sync;
+ Collection c;
+
+ public SynchronizedCollection(Collection c)
+ {
+ this.sync = this;
+ this.c = c;
+ }
+ public SynchronizedCollection(Object sync, Collection c)
+ {
+ this.c = c;
+ this.sync = sync;
+ }
+
+ public boolean add(Object o)
+ {
+ synchronized(sync)
+ {
+ return c.add(o);
+ }
+ }
+ public boolean addAll(Collection col)
+ {
+ synchronized(sync)
+ {
+ return c.addAll(col);
+ }
+ }
+ public void clear()
+ {
+ synchronized(sync)
+ {
+ c.clear();
+ }
+ }
+ public boolean contains(Object o)
+ {
+ synchronized(sync)
+ {
+ return c.contains(o);
+ }
+ }
+ public boolean containsAll(Collection c1)
+ {
+ synchronized(sync)
+ {
+ return c.containsAll(c1);
+ }
+ }
+ public boolean isEmpty()
+ {
+ synchronized(sync)
+ {
+ return c.isEmpty();
+ }
+ }
+ public Iterator iterator()
+ {
+ synchronized(sync)
+ {
+ return new SynchronizedIterator(sync, c.iterator());
+ }
+ }
+ public boolean remove(Object o)
+ {
+ synchronized(sync)
+ {
+ return c.remove(o);
+ }
+ }
+ public boolean removeAll(Collection col)
+ {
+ synchronized(sync)
+ {
+ return c.removeAll(col);
+ }
+ }
+ public boolean retainAll(Collection col)
+ {
+ synchronized(sync)
+ {
+ return c.retainAll(col);
+ }
+ }
+ public int size()
+ {
+ synchronized(sync)
+ {
+ return c.size();
+ }
+ }
+ public Object[] toArray()
+ {
+ synchronized(sync)
+ {
+ return c.toArray();
+ }
+ }
+ public Object[] toArray(Object[]a)
+ {
+ synchronized(sync)
+ {
+ return c.toArray(a);
+ }
+ }
+ }
+
+ private static class SynchronizedList extends SynchronizedCollection
+ implements List
+ {
+
+ // This is stored both here and in the superclass, to avoid excessive
+ // casting.
+ List l;
+
+ public SynchronizedList(Object sync, List l)
+ {
+ super(sync, l);
+ this.l = l;
+ }
+ public SynchronizedList(List l)
+ {
+ super(l);
+ }
+
+ public void add(int index, Object o)
+ {
+ synchronized(sync)
+ {
+ l.add(index, o);
+ }
+ }
+ public boolean addAll(int index, Collection c)
+ {
+ synchronized(sync)
+ {
+ return l.addAll(index, c);
+ }
+ }
+ public boolean equals(Object o)
+ {
+ synchronized(sync)
+ {
+ return l.equals(o);
+ }
+ }
+ public Object get(int index)
+ {
+ synchronized(sync)
+ {
+ return l.get(index);
+ }
+ }
+ public int hashCode()
+ {
+ synchronized(sync)
+ {
+ return l.hashCode();
+ }
+ }
+ public int indexOf(Object o)
+ {
+ synchronized(sync)
+ {
+ return l.indexOf(o);
+ }
+ }
+ public int lastIndexOf(Object o)
+ {
+ synchronized(sync)
+ {
+ return l.lastIndexOf(o);
+ }
+ }
+ public ListIterator listIterator()
+ {
+ synchronized(sync)
+ {
+ return new SynchronizedListIterator(sync, l.listIterator());
+ }
+ }
+ public ListIterator listIterator(int index)
+ {
+ synchronized(sync)
+ {
+ return new SynchronizedListIterator(sync, l.listIterator(index));
+ }
+ }
+ public Object remove(int index)
+ {
+ synchronized(sync)
+ {
+ return l.remove(index);
+ }
+ }
+ public boolean remove(Object o)
+ {
+ synchronized(sync)
+ {
+ return l.remove(o);
+ }
+ }
+ public Object set(int index, Object o)
+ {
+ synchronized(sync)
+ {
+ return l.set(index, o);
+ }
+ }
+ public List subList(int fromIndex, int toIndex)
+ {
+ synchronized(sync)
+ {
+ return new SynchronizedList(l.subList(fromIndex, toIndex));
+ }
+ }
+ }
+
+ private static class SynchronizedSet extends SynchronizedCollection
+ implements Set
+ {
+
+ public SynchronizedSet(Object sync, Set s)
+ {
+ super(sync, s);
+ }
+ public SynchronizedSet(Set s)
+ {
+ super(s);
+ }
+
+ public boolean equals(Object o)
+ {
+ synchronized(sync)
+ {
+ return c.equals(o);
+ }
+ }
+ public int hashCode()
+ {
+ synchronized(sync)
+ {
+ return c.hashCode();
+ }
+ }
+ }
+
+ 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)
+ {
+ super(sync, ss);
+ this.ss = ss;
+ }
+ public SynchronizedSortedSet(SortedSet ss)
+ {
+ super(ss);
+ }
+
+ public Comparator comparator()
+ {
+ synchronized(sync)
+ {
+ return ss.comparator();
+ }
+ }
+ public Object first()
+ {
+ 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));
+ }
+ }
+ }
+
+ private static class SynchronizedMap implements Map, Serializable
+ {
+
+ Object sync;
+ Map m;
+
+ public SynchronizedMap(Object sync, Map m)
+ {
+ this.sync = sync;
+ this.m = m;
+ }
+ public SynchronizedMap(Map m)
+ {
+ this.m = m;
+ this.sync = this;
+ }
+
+ public void clear()
+ {
+ synchronized(sync)
+ {
+ m.clear();
+ }
+ }
+ public boolean containsKey(Object key)
+ {
+ synchronized(sync)
+ {
+ return m.containsKey(key);
+ }
+ }
+ public boolean containsValue(Object value)
+ {
+ synchronized(sync)
+ {
+ return m.containsValue(value);
+ }
+ }
+
+ // This is one of the ickiest cases of nesting I've ever seen. It just
+ // means "return an SynchronizedSet, except that the iterator() method
+ // returns an SynchronizedIterator whos next() method returns a
+ // synchronized wrapper around its normal return value".
+ public Set entrySet()
+ {
+ synchronized(sync)
+ {
+ return new SynchronizedSet(sync, m.entrySet())
+ {
+ public Iterator iterator()
+ {
+ synchronized(SynchronizedMap.this.sync)
+ {
+ 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);
+ }
+ }
+ };
+ }
+ }
+ };
+ }
+ }
+ };
+ }
+ }
+ public boolean equals(Object o)
+ {
+ synchronized(sync)
+ {
+ return m.equals(o);
+ }
+ }
+ public Object get(Object key)
+ {
+ synchronized(sync)
+ {
+ return m.get(key);
+ }
+ }
+ public Object put(Object key, Object value)
+ {
+ synchronized(sync)
+ {
+ return m.put(key, value);
+ }
+ }
+ public int hashCode()
+ {
+ synchronized(sync)
+ {
+ return m.hashCode();
+ }
+ }
+ public boolean isEmpty()
+ {
+ synchronized(sync)
+ {
+ return m.isEmpty();
+ }
+ }
+ public Set keySet()
+ {
+ synchronized(sync)
+ {
+ return new SynchronizedSet(sync, m.keySet());
+ }
+ }
+ public void putAll(Map map)
+ {
+ synchronized(sync)
+ {
+ m.putAll(map);
+ }
+ }
+ public Object remove(Object o)
+ {
+ synchronized(sync)
+ {
+ return m.remove(o);
+ }
+ }
+
+ public int size()
+ {
+ synchronized(sync)
+ {
+ return m.size();
+ }
+ }
+ public Collection values()
+ {
+ synchronized(sync)
+ {
+ return new SynchronizedCollection(sync, m.values());
+ }
+ }
+ }
+
+ private static class SynchronizedSortedMap extends SynchronizedMap
+ implements SortedMap
+ {
+
+ // This is stored both here and in the superclass, to avoid excessive
+ // casting.
+ private SortedMap sm;
+
+ public SynchronizedSortedMap(Object sync, SortedMap sm)
+ {
+ super(sync, sm);
+ this.sm = sm;
+ }
+ public SynchronizedSortedMap(SortedMap sm)
+ {
+ super(sm);
+ }
+
+ public Comparator comparator()
+ {
+ synchronized(sync)
+ {
+ return sm.comparator();
+ }
+ }
+ public Object firstKey()
+ {
+ synchronized(sync)
+ {
+ return sm.firstKey();
+ }
+ }
+ public Object lastKey()
+ {
+ synchronized(sync)
+ {
+ return sm.lastKey();
+ }
+ }
+ public SortedMap headMap(Object toKey)
+ {
+ return new SynchronizedSortedMap(sync, sm.headMap(toKey));
+ }
+ public SortedMap tailMap(Object fromKey)
+ {
+ return new SynchronizedSortedMap(sync, sm.tailMap(fromKey));
+ }
+ public SortedMap subMap(Object fromKey, Object toKey)
+ {
+ return new SynchronizedSortedMap(sync, sm.subMap(fromKey, toKey));
+ }
+ }
+}