/* Collections.java -- Utility class with methods to operate on collections
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import gnu.java.lang.CPStringBuilder;
import java.io.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.
*
*
* 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,
* Collections.singleton("").addAll(Collections.EMPTY_SET)
* 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)
* @author Tom Tromey (tromey@redhat.com)
* @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see Collection
* @see Set
* @see List
* @see Map
* @see Arrays
* @since 1.2
* @status updated to 1.5
*/
public class Collections
{
/**
* Constant used to decide cutoff for when a non-RandomAccess list should
* be treated as sequential-access. Basically, quadratic behavior is
* acceptable 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.
*/
private Collections()
{
}
/**
* An immutable, serializable, empty Set.
* @see Serializable
*/
public static final Set EMPTY_SET = new EmptySet();
/**
* Returns an immutable, serializable parameterized empty set.
* Unlike the constant EMPTY_SET, the set returned by
* this method is type-safe.
*
* @return an empty parameterized set.
* @since 1.5
*/
public static final Set emptySet()
{
/* FIXME: Could this be optimized? */
return 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)
*/
private static final class EmptySet extends AbstractSet
implements Serializable
{
/**
* Compatible with JDK 1.4.
*/
private static final long serialVersionUID = 1582296315990362920L;
/**
* A private constructor adds overhead.
*/
EmptySet()
{
}
/**
* The size: always 0!
* @return 0.
*/
public int size()
{
return 0;
}
/**
* Returns an iterator that does not iterate.
* @return A non-iterating iterator.
*/
// This is really cheating! I think it's perfectly valid, though.
public Iterator iterator()
{
return (Iterator) EMPTY_LIST.iterator();
}
// The remaining methods are optional, but provide a performance
// advantage by not allocating unnecessary iterators in AbstractSet.
/**
* The empty set never contains anything.
* @param o The object to search for.
* @return false.
*/
public boolean contains(Object o)
{
return false;
}
/**
* This is true only if the given collection is also empty.
* @param c The collection of objects which are to be compared
* against the members of this set.
* @return true if c is empty.
*/
public boolean containsAll(Collection> c)
{
return c.isEmpty();
}
/**
* Equal only if the other set is empty.
* @param o The object to compare with this set.
* @return true if o is an empty instance of Set.
*/
public boolean equals(Object o)
{
return o instanceof Set && ((Set) o).isEmpty();
}
/**
* The hashcode is always 0.
* @return 0.
*/
public int hashCode()
{
return 0;
}
/**
* Always succeeds with a false result.
* @param o The object to remove.
* @return false.
*/
public boolean remove(Object o)
{
return false;
}
/**
* Always succeeds with a false result.
* @param c The collection of objects which should
* all be removed from this set.
* @return false.
*/
public boolean removeAll(Collection> c)
{
return false;
}
/**
* Always succeeds with a false result.
* @param c The collection of objects which should
* all be retained within this set.
* @return false.
*/
public boolean retainAll(Collection> c)
{
return false;
}
/**
* The array is always empty.
* @return A new array with a size of 0.
*/
public Object[] toArray()
{
return new Object[0];
}
/**
* We don't even need to use reflection!
* @param a An existing array, which can be empty.
* @return The original array with any existing
* initial element set to null.
*/
public E[] toArray(E[] a)
{
if (a.length > 0)
a[0] = null;
return a;
}
/**
* The string never changes.
*
* @return the string "[]".
*/
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();
/**
* Returns an immutable, serializable parameterized empty list.
* Unlike the constant EMPTY_LIST, the list returned by
* this method is type-safe.
*
* @return an empty parameterized list.
* @since 1.5
*/
public static final List emptyList()
{
/* FIXME: Could this be optimized? */
return 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)
*/
private static final class EmptyList extends AbstractList
implements Serializable, RandomAccess
{
/**
* Compatible with JDK 1.4.
*/
private static final long serialVersionUID = 8842843931221139166L;
/**
* A private constructor adds overhead.
*/
EmptyList()
{
}
/**
* The size is always 0.
* @return 0.
*/
public int size()
{
return 0;
}
/**
* No matter the index, it is out of bounds. This
* method never returns, throwing an exception instead.
*
* @param index The index of the element to retrieve.
* @return the object at the specified index.
* @throws IndexOutOfBoundsException as any given index
* is outside the bounds of an empty array.
*/
public T get(int index)
{
throw new IndexOutOfBoundsException();
}
// The remaining methods are optional, but provide a performance
// advantage by not allocating unnecessary iterators in AbstractList.
/**
* Never contains anything.
* @param o The object to search for.
* @return false.
*/
public boolean contains(Object o)
{
return false;
}
/**
* This is true only if the given collection is also empty.
* @param c The collection of objects, which should be compared
* against the members of this list.
* @return true if c is also empty.
*/
public boolean containsAll(Collection> c)
{
return c.isEmpty();
}
/**
* Equal only if the other list is empty.
* @param o The object to compare against this list.
* @return true if o is also an empty instance of
* List.
*/
public boolean equals(Object o)
{
return o instanceof List && ((List) o).isEmpty();
}
/**
* The hashcode is always 1.
* @return 1.
*/
public int hashCode()
{
return 1;
}
/**
* Returns -1.
* @param o The object to search for.
* @return -1.
*/
public int indexOf(Object o)
{
return -1;
}
/**
* Returns -1.
* @param o The object to search for.
* @return -1.
*/
public int lastIndexOf(Object o)
{
return -1;
}
/**
* Always succeeds with false result.
* @param o The object to remove.
* @return -1.
*/
public boolean remove(Object o)
{
return false;
}
/**
* Always succeeds with false result.
* @param c The collection of objects which should
* all be removed from this list.
* @return false.
*/
public boolean removeAll(Collection> c)
{
return false;
}
/**
* Always succeeds with false result.
* @param c The collection of objects which should
* all be retained within this list.
* @return false.
*/
public boolean retainAll(Collection> c)
{
return false;
}
/**
* The array is always empty.
* @return A new array with a size of 0.
*/
public Object[] toArray()
{
return new Object[0];
}
/**
* We don't even need to use reflection!
* @param a An existing array, which can be empty.
* @return The original array with any existing
* initial element set to null.
*/
public E[] toArray(E[] a)
{
if (a.length > 0)
a[0] = null;
return a;
}
/**
* The string never changes.
*
* @return the string "[]".
*/
public String toString()
{
return "[]";
}
} // class EmptyList
/**
* An immutable, serializable, empty Map.
* @see Serializable
*/
public static final Map EMPTY_MAP = new EmptyMap();
/**
* Returns an immutable, serializable parameterized empty map.
* Unlike the constant EMPTY_MAP, the map returned by
* this method is type-safe.
*
* @return an empty parameterized map.
* @since 1.5
*/
public static final Map emptyMap()
{
/* FIXME: Could this be optimized? */
return new EmptyMap();
}
/**
* 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)
*/
private static final class EmptyMap extends AbstractMap
implements Serializable
{
/**
* Compatible with JDK 1.4.
*/
private static final long serialVersionUID = 6428348081105594320L;
/**
* A private constructor adds overhead.
*/
EmptyMap()
{
}
/**
* There are no entries.
* @return The empty set.
*/
public Set> entrySet()
{
return EMPTY_SET;
}
// The remaining methods are optional, but provide a performance
// advantage by not allocating unnecessary iterators in AbstractMap.
/**
* No entries!
* @param key The key to search for.
* @return false.
*/
public boolean containsKey(Object key)
{
return false;
}
/**
* No entries!
* @param value The value to search for.
* @return false.
*/
public boolean containsValue(Object value)
{
return false;
}
/**
* Equal to all empty maps.
* @param o The object o to compare against this map.
* @return true if o is also an empty instance of
* Map.
*/
public boolean equals(Object o)
{
return o instanceof Map && ((Map) o).isEmpty();
}
/**
* No mappings, so this returns null.
* @param o The key of the object to retrieve.
* @return null.
*/
public V get(Object o)
{
return null;
}
/**
* The hashcode is always 0.
* @return 0.
*/
public int hashCode()
{
return 0;
}
/**
* No entries.
* @return The empty set.
*/
public Set keySet()
{
return EMPTY_SET;
}
/**
* Remove always succeeds, with null result.
* @param o The key of the mapping to remove.
* @return null, as there is never a mapping for o.
*/
public V remove(Object o)
{
return null;
}
/**
* Size is always 0.
* @return 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!
* @return The empty set.
*/
public Collection values()
{
return EMPTY_SET;
}
/**
* The string never changes.
*
* @return the string "[]".
*/
public String toString()
{
return "[]";
}
} // 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).
*/
static final int compare(T o1, T o2, Comparator super T> c)
{
return c == null ? ((Comparable) o1).compareTo(o2) : c.compare(o1, o2);
}
/**
* 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
* 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.
*
*
* 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.
*
* @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)
*/
public static int binarySearch(List extends Comparable super T>> l,
T key)
{
return binarySearch(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
* 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.
*
*
* 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.
*
* @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)
*/
public static int binarySearch(List extends T> l, T key,
Comparator super T> 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 = ((List) l).listIterator();
int i = 0;
T o = itr.next(); // Assumes list is not empty (see isSequential)
boolean forward = true;
while (low <= hi)
{
pos = (low + hi) >>> 1;
if (i < pos)
{
if (!forward)
itr.next(); // Changing direction first.
for ( ; i != pos; i++, o = itr.next())
;
forward = true;
}
else
{
if (forward)
itr.previous(); // Changing direction first.
for ( ; i != pos; i--, o = itr.previous())
;
forward = false;
}
final int d = compare(o, key, 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
{
while (low <= hi)
{
pos = (low + hi) >>> 1;
final int d = compare(((List) l).get(pos), key, 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;
}
}
// If we failed to find it, we do the same whichever search we did.
return -pos - 1;
}
/**
* 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
* @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
*/
public static void copy(List super T> dest, List extends T> source)
{
int pos = source.size();
if (dest.size() < pos)
throw new IndexOutOfBoundsException("Source does not fit in dest");
Iterator extends T> i1 = source.iterator();
ListIterator super T> i2 = dest.listIterator();
while (--pos >= 0)
{
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
* @return an Enumeration backed by an Iterator over c
*/
public static Enumeration enumeration(Collection c)
{
final Iterator i = c.iterator();
return new Enumeration()
{
/**
* Returns true if there are more elements to
* be enumerated.
*
* @return The result of hasNext()
* called on the underlying iterator.
*/
public final boolean hasMoreElements()
{
return i.hasNext();
}
/**
* Returns the next element to be enumerated.
*
* @return The result of next()
* called on the underlying iterator.
*/
public final T 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.
* @throws UnsupportedOperationException if l.listIterator() does not
* support the set operation.
*/
public static void fill(List super T> l, T val)
{
ListIterator super T> itr = l.listIterator();
for (int i = l.size() - 1; i >= 0; --i)
{
itr.next();
itr.set(val);
}
}
/**
* Returns the starting index where the specified sublist first occurs
* in a larger list, or -1 if there is no matching position. If
* target.size() > source.size(), this returns -1,
* otherwise this implementation uses brute force, checking for
* source.sublist(i, i + target.size()).equals(target)
* 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
* target.size() > source.size(), this returns -1,
* otherwise this implementation uses brute force, checking for
* source.sublist(i, i + target.size()).equals(target)
* 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 ArrayList 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 ArrayList list(Enumeration e)
{
ArrayList 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
* @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 >
T max(Collection extends T> c)
{
return max(c, null);
}
/**
* 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, 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)
*/
public static T max(Collection extends T> c,
Comparator super T> order)
{
Iterator extends T> itr = c.iterator();
T max = itr.next(); // throws NoSuchElementException
int csize = c.size();
for (int i = 1; i < csize; i++)
{
T o = itr.next();
if (compare(max, o, order) < 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
* @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
*/
public static >
T min(Collection extends T> c)
{
return min(c, null);
}
/**
* 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, 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)
*/
public static T min(Collection extends T> c,
Comparator super T> order)
{
Iterator extends T> itr = c.iterator();
T min = itr.next(); // throws NoSuchElementExcception
int csize = c.size();
for (int i = 1; i < csize; i++)
{
T o = itr.next();
if (compare(min, o, order) > 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, and
* implements RandomAccess. You can use it in tandem with List.addAll for
* fast list construction.
*
* @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
*/
public static List nCopies(final int n, final T 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 T element;
/**
* Constructs the list.
*
* @param n the count
* @param o the object
* @throws IllegalArgumentException if n < 0
*/
CopiesList(int n, T o)
{
if (n < 0)
throw new IllegalArgumentException();
this.n = n;
element = o;
}
/**
* The size is fixed.
* @return The size of the list.
*/
public int size()
{
return n;
}
/**
* The same element is returned.
* @param index The index of the element to be returned (irrelevant
* as the list contains only copies of element).
* @return The element used by this list.
*/
public T 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.
* @param o The object to search for.
* @return true if o is the element used by this list.
*/
public boolean contains(Object o)
{
return n > 0 && equals(o, element);
}
/**
* The index is either 0 or -1.
* @param o The object to find the index of.
* @return 0 if o == element, -1 if not.
*/
public int indexOf(Object o)
{
return (n > 0 && equals(o, element)) ? 0 : -1;
}
/**
* The index is either n-1 or -1.
* @param o The object to find the last index of.
* @return The last index in the list if o == element,
* -1 if not.
*/
public int lastIndexOf(Object o)
{
return equals(o, element) ? n - 1 : -1;
}
/**
* A subList is just another CopiesList.
* @param from The starting bound of the sublist.
* @param to The ending bound of the sublist.
* @return A list of copies containing from - to
* elements, all of which are equal to the element
* used by this list.
*/
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.
* @return An array of size n filled with copies of
* the element used by this list.
*/
public Object[] toArray()
{
Object[] a = new Object[n];
Arrays.fill(a, element);
return a;
}
/**
* The string is easy to generate.
* @return A string representation of the list.
*/
public String toString()
{
CPStringBuilder r = new CPStringBuilder("{");
for (int i = n - 1; --i > 0; )
r.append(element).append(", ");
r.append(element).append("}");
return r.toString();
}
} // class CopiesList
/**
* Replace all instances of one object with another in the specified list.
* The list does not change size. An element e is replaced if
* oldval == null ? e == null : oldval.equals(e).
*
* @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 if newval is of a type which cannot be added
* to the list
* @throws IllegalArgumentException if some other aspect of newval stops
* it being added to the list
* @since 1.4
*/
public static boolean replaceAll(List list, T oldval, T 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;
}
/**
* 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
*/
public static void reverse(List> l)
{
ListIterator i1 = l.listIterator();
int pos1 = 1;
int pos2 = l.size();
ListIterator i2 = l.listIterator(pos2);
while (pos1 < pos2)
{
Object o1 = i1.next();
Object o2 = i2.previous();
i1.set(o2);
i2.set(o1);
++pos1;
--pos2;
}
}
/**
* Get a comparator that implements the reverse of the ordering
* specified by the given Comparator. If the Comparator is null,
* this is equivalent to {@link #reverseOrder()}. The return value
* of this method is Serializable, if the specified Comparator is
* either Serializable or null.
*
* @param c the comparator to invert
* @return a comparator that imposes reverse ordering
* @see Comparable
* @see Serializable
*
* @since 1.5
*/
public static Comparator reverseOrder(final Comparator c)
{
if (c == null)
return (Comparator) rcInstance;
return new ReverseComparator ()
{
public int compare(T a, T b)
{
return - c.compare(a, b);
}
};
}
/**
* 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 (Comparator) rcInstance;
}
/**
* The object for {@link #reverseOrder()}.
*/
private static 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 class ReverseComparator
implements Comparator, Serializable
{
/**
* Compatible with JDK 1.4.
*/
private static 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(T a, T b)
{
return ((Comparable) b).compareTo(a);
}
}
/**
* Rotate the elements in a list by a specified distance. After calling this
* method, the element now at index i was formerly at index
* (i - distance) mod list.size(). The list size is unchanged.
*
*
* For example, suppose a list contains [t, a, n, k, s]. After
* either Collections.rotate(l, 4) or
* Collections.rotate(l, -1), the new contents are
* [s, t, a, n, k]. This can be applied to sublists to rotate
* just a portion of the list. For example, to move element a
* forward two positions in the original example, use
* Collections.rotate(l.subList(1, 3+1), -1), which will
* result in [t, n, k, a, s].
*
*
* 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
* -distance mod size, 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();
if (size == 0)
return;
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.
List