3966 lines · 152.7 KB · Java
RawDownload
/* * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.util;import java.io.Serializable;import java.io.ObjectOutputStream;import java.io.IOException;import java.lang.reflect.Array; /** * This class consists exclusively of static methods that operate on or return * collections.  It contains polymorphic algorithms that operate on * collections, "wrappers", which return a new collection backed by a * specified collection, and a few other odds and ends. * * <p>The methods of this class all throw a <tt>NullPointerException</tt> * if the collections or class objects provided to them are null. * * <p>The documentation for the polymorphic algorithms contained in this class * generally includes a brief description of the <i>implementation</i>.  Such * descriptions should be regarded as <i>implementation notes</i>, rather than * parts of the <i>specification</i>.  Implementors should feel free to * substitute other algorithms, so long as the specification itself is adhered * to.  (For example, the algorithm used by <tt>sort</tt> does not have to be * a mergesort, but it does have to be <i>stable</i>.) * * <p>The "destructive" algorithms contained in this class, that is, the * algorithms that modify the collection on which they operate, are specified * to throw <tt>UnsupportedOperationException</tt> if the collection does not * support the appropriate mutation primitive(s), such as the <tt>set</tt> * method.  These algorithms may, but are not required to, throw this * exception if an invocation would have no effect on the collection.  For * example, invoking the <tt>sort</tt> method on an unmodifiable list that is * already sorted may or may not throw <tt>UnsupportedOperationException</tt>. * * <p>This class is a member of the * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author  Josh Bloch * @author  Neal Gafter * @see     Collection * @see     Set * @see     List * @see     Map * @since   1.2 */ public class Collections {    // Suppresses default constructor, ensuring non-instantiability.    private Collections() {    }     // Algorithms     /*     * Tuning parameters for algorithms - Many of the List algorithms have     * two implementations, one of which is appropriate for RandomAccess     * lists, the other for "sequential."  Often, the random access variant     * yields better performance on small sequential access lists.  The     * tuning parameters below determine the cutoff point for what constitutes     * a "small" sequential access list for each algorithm.  The values below     * were empirically determined to work well for LinkedList. Hopefully     * they should be reasonable for other sequential access List     * implementations.  Those doing performance work on this code would     * do well to validate the values of these parameters from time to time.     * (The first word of each tuning parameter name is the algorithm to which     * it applies.)     */    private static final int BINARYSEARCH_THRESHOLD   = 5000;    private static final int REVERSE_THRESHOLD        =   18;    private static final int SHUFFLE_THRESHOLD        =    5;    private static final int FILL_THRESHOLD           =   25;    private static final int ROTATE_THRESHOLD         =  100;    private static final int COPY_THRESHOLD           =   10;    private static final int REPLACEALL_THRESHOLD     =   11;    private static final int INDEXOFSUBLIST_THRESHOLD =   35;     /**     * Sorts the specified list into ascending order, according to the     * {@linkplain Comparable natural ordering} of its elements.     * All elements in the list must implement the {@link Comparable}     * interface.  Furthermore, all elements in the list must be     * <i>mutually comparable</i> (that is, {@code e1.compareTo(e2)}     * must not throw a {@code ClassCastException} for any elements     * {@code e1} and {@code e2} in the list).     *     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will     * not be reordered as a result of the sort.     *     * <p>The specified list must be modifiable, but need not be resizable.     *     * <p>Implementation note: This implementation is a stable, adaptive,     * iterative mergesort that requires far fewer than n lg(n) comparisons     * when the input array is partially sorted, while offering the     * performance of a traditional mergesort when the input array is     * randomly ordered.  If the input array is nearly sorted, the     * implementation requires approximately n comparisons.  Temporary     * storage requirements vary from a small constant for nearly sorted     * input arrays to n/2 object references for randomly ordered input     * arrays.     *     * <p>The implementation takes equal advantage of ascending and     * descending order in its input array, and can take advantage of     * ascending and descending order in different parts of the same     * input array.  It is well-suited to merging two or more sorted arrays:     * simply concatenate the arrays and sort the resulting array.     *     * <p>The implementation was adapted from Tim Peters's list sort for Python     * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">     * TimSort</a>).  It uses techiques from Peter McIlroy's "Optimistic     * Sorting and Information Theoretic Complexity", in Proceedings of the     * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,     * January 1993.     *     * <p>This implementation dumps the specified list into an array, sorts     * the array, and iterates over the list resetting each element     * from the corresponding position in the array.  This avoids the     * n<sup>2</sup> log(n) performance that would result from attempting     * to sort a linked list in place.     *     * @param  list the list to be sorted.     * @throws ClassCastException if the list contains elements that are not     *         <i>mutually comparable</i> (for example, strings and integers).     * @throws UnsupportedOperationException if the specified list's     *         list-iterator does not support the {@code set} operation.     * @throws IllegalArgumentException (optional) if the implementation     *         detects that the natural ordering of the list elements is     *         found to violate the {@link Comparable} contract     */    public static <T extends Comparable<? super T>> void sort(List<T> list) {        Object[] a = list.toArray();        Arrays.sort(a);        ListIterator<T> i = list.listIterator();        for (int j=0; j<a.length; j++) {            i.next();            i.set((T)a[j]);        }    }     /**     * Sorts the specified list according to the order induced by the     * specified comparator.  All elements in the list must be <i>mutually     * comparable</i> using the specified comparator (that is,     * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}     * for any elements {@code e1} and {@code e2} in the list).     *     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will     * not be reordered as a result of the sort.     *     * <p>The specified list must be modifiable, but need not be resizable.     *     * <p>Implementation note: This implementation is a stable, adaptive,     * iterative mergesort that requires far fewer than n lg(n) comparisons     * when the input array is partially sorted, while offering the     * performance of a traditional mergesort when the input array is     * randomly ordered.  If the input array is nearly sorted, the     * implementation requires approximately n comparisons.  Temporary     * storage requirements vary from a small constant for nearly sorted     * input arrays to n/2 object references for randomly ordered input     * arrays.     *     * <p>The implementation takes equal advantage of ascending and     * descending order in its input array, and can take advantage of     * ascending and descending order in different parts of the same     * input array.  It is well-suited to merging two or more sorted arrays:     * simply concatenate the arrays and sort the resulting array.     *     * <p>The implementation was adapted from Tim Peters's list sort for Python     * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">     * TimSort</a>).  It uses techiques from Peter McIlroy's "Optimistic     * Sorting and Information Theoretic Complexity", in Proceedings of the     * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,     * January 1993.     *     * <p>This implementation dumps the specified list into an array, sorts     * the array, and iterates over the list resetting each element     * from the corresponding position in the array.  This avoids the     * n<sup>2</sup> log(n) performance that would result from attempting     * to sort a linked list in place.     *     * @param  list the list to be sorted.     * @param  c the comparator to determine the order of the list.  A     *        {@code null} value indicates that the elements' <i>natural     *        ordering</i> should be used.     * @throws ClassCastException if the list contains elements that are not     *         <i>mutually comparable</i> using the specified comparator.     * @throws UnsupportedOperationException if the specified list's     *         list-iterator does not support the {@code set} operation.     * @throws IllegalArgumentException (optional) if the comparator is     *         found to violate the {@link Comparator} contract     */    public static <T> void sort(List<T> list, Comparator<? super T> c) {        Object[] a = list.toArray();        Arrays.sort(a, (Comparator)c);        ListIterator i = list.listIterator();        for (int j=0; j<a.length; j++) {            i.next();            i.set(a[j]);        }    }      /**     * Searches the specified list for the specified object using the binary     * search algorithm.  The list must be sorted into ascending order     * according to the {@linkplain Comparable natural ordering} of its     * elements (as by the {@link #sort(List)} method) prior to making this     * call.  If it is not sorted, the results are undefined.  If the list     * contains multiple elements equal to the specified object, there is no     * guarantee which one will be found.     *     * <p>This method runs in log(n) time for a "random access" list (which     * provides near-constant-time positional access).  If the specified list     * does not implement the {@link RandomAccess} interface and is large,     * this method will do an iterator-based binary search that performs     * O(n) link traversals and O(log n) element comparisons.     *     * @param  list the list to be searched.     * @param  key the key to be searched for.     * @return the index of the search key, if it is contained in the list;     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The     *         <i>insertion point</i> is defined as the point at which the     *         key would be inserted into the list: the index of the first     *         element greater than the key, or <tt>list.size()</tt> if all     *         elements in the list are less than the specified key.  Note     *         that this guarantees that the return value will be &gt;= 0 if     *         and only if the key is found.     * @throws ClassCastException if the list contains elements that are not     *         <i>mutually comparable</i> (for example, strings and     *         integers), or the search key is not mutually comparable     *         with the elements of the list.     */    public static <T>    int binarySearch(List<? extends Comparable<? super T>> list, T key) {        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)            return Collections.indexedBinarySearch(list, key);        else            return Collections.iteratorBinarySearch(list, key);    }     private static <T>    int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key)    {        int low = 0;        int high = list.size()-1;         while (low <= high) {            int mid = (low + high) >>> 1;            Comparable<? super T> midVal = list.get(mid);            int cmp = midVal.compareTo(key);             if (cmp < 0)                low = mid + 1;            else if (cmp > 0)                high = mid - 1;            else                return mid; // key found        }        return -(low + 1);  // key not found    }     private static <T>    int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)    {        int low = 0;        int high = list.size()-1;        ListIterator<? extends Comparable<? super T>> i = list.listIterator();         while (low <= high) {            int mid = (low + high) >>> 1;            Comparable<? super T> midVal = get(i, mid);            int cmp = midVal.compareTo(key);             if (cmp < 0)                low = mid + 1;            else if (cmp > 0)                high = mid - 1;            else                return mid; // key found        }        return -(low + 1);  // key not found    }     /**     * Gets the ith element from the given list by repositioning the specified     * list listIterator.     */    private static <T> T get(ListIterator<? extends T> i, int index) {        T obj = null;        int pos = i.nextIndex();        if (pos <= index) {            do {                obj = i.next();            } while (pos++ < index);        } else {            do {                obj = i.previous();            } while (--pos > index);        }        return obj;    }     /**     * Searches the specified list for the specified object using the binary     * search algorithm.  The list must be sorted into ascending order     * according to the specified comparator (as by the     * {@link #sort(List, Comparator) sort(List, Comparator)}     * method), prior to making this call.  If it is     * not sorted, the results are undefined.  If the list contains multiple     * elements equal to the specified object, there is no guarantee which one     * will be found.     *     * <p>This method runs in log(n) time for a "random access" list (which     * provides near-constant-time positional access).  If the specified list     * does not implement the {@link RandomAccess} interface and is large,     * this method will do an iterator-based binary search that performs     * O(n) link traversals and O(log n) element comparisons.     *     * @param  list the list to be searched.     * @param  key the key to be searched for.     * @param  c the comparator by which the list is ordered.     *         A <tt>null</tt> value indicates that the elements'     *         {@linkplain Comparable natural ordering} should be used.     * @return the index of the search key, if it is contained in the list;     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The     *         <i>insertion point</i> is defined as the point at which the     *         key would be inserted into the list: the index of the first     *         element greater than the key, or <tt>list.size()</tt> if all     *         elements in the list are less than the specified key.  Note     *         that this guarantees that the return value will be &gt;= 0 if     *         and only if the key is found.     * @throws ClassCastException if the list contains elements that are not     *         <i>mutually comparable</i> using the specified comparator,     *         or the search key is not mutually comparable with the     *         elements of the list using this comparator.     */    public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c) {        if (c==null)            return binarySearch((List) list, key);         if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)            return Collections.indexedBinarySearch(list, key, c);        else            return Collections.iteratorBinarySearch(list, key, c);    }     private static <T> int indexedBinarySearch(List<? extends T> l, T key, Comparator<? super T> c) {        int low = 0;        int high = l.size()-1;         while (low <= high) {            int mid = (low + high) >>> 1;            T midVal = l.get(mid);            int cmp = c.compare(midVal, key);             if (cmp < 0)                low = mid + 1;            else if (cmp > 0)                high = mid - 1;            else                return mid; // key found        }        return -(low + 1);  // key not found    }     private static <T> int iteratorBinarySearch(List<? extends T> l, T key, Comparator<? super T> c) {        int low = 0;        int high = l.size()-1;        ListIterator<? extends T> i = l.listIterator();         while (low <= high) {            int mid = (low + high) >>> 1;            T midVal = get(i, mid);            int cmp = c.compare(midVal, key);             if (cmp < 0)                low = mid + 1;            else if (cmp > 0)                high = mid - 1;            else                return mid; // key found        }        return -(low + 1);  // key not found    }     private interface SelfComparable extends Comparable<SelfComparable> {}      /**     * Reverses the order of the elements in the specified list.<p>     *     * This method runs in linear time.     *     * @param  list the list whose elements are to be reversed.     * @throws UnsupportedOperationException if the specified list or     *         its list-iterator does not support the <tt>set</tt> operation.     */    public static void reverse(List<?> list) {        int size = list.size();        if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {            for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)                swap(list, i, j);        } else {            ListIterator fwd = list.listIterator();            ListIterator rev = list.listIterator(size);            for (int i=0, mid=list.size()>>1; i<mid; i++) {                Object tmp = fwd.next();                fwd.set(rev.previous());                rev.set(tmp);            }        }    }     /**     * Randomly permutes the specified list using a default source of     * randomness.  All permutations occur with approximately equal     * likelihood.<p>     *     * The hedge "approximately" is used in the foregoing description because     * default source of randomness is only approximately an unbiased source     * of independently chosen bits. If it were a perfect source of randomly     * chosen bits, then the algorithm would choose permutations with perfect     * uniformity.<p>     *     * This implementation traverses the list backwards, from the last element     * up to the second, repeatedly swapping a randomly selected element into     * the "current position".  Elements are randomly selected from the     * portion of the list that runs from the first element to the current     * position, inclusive.<p>     *     * This method runs in linear time.  If the specified list does not     * implement the {@link RandomAccess} interface and is large, this     * implementation dumps the specified list into an array before shuffling     * it, and dumps the shuffled array back into the list.  This avoids the     * quadratic behavior that would result from shuffling a "sequential     * access" list in place.     *     * @param  list the list to be shuffled.     * @throws UnsupportedOperationException if the specified list or     *         its list-iterator does not support the <tt>set</tt> operation.     */    public static void shuffle(List<?> list) {        Random rnd = r;        if (rnd == null)            r = rnd = new Random();        shuffle(list, rnd);    }    private static Random r;     /**     * Randomly permute the specified list using the specified source of     * randomness.  All permutations occur with equal likelihood     * assuming that the source of randomness is fair.<p>     *     * This implementation traverses the list backwards, from the last element     * up to the second, repeatedly swapping a randomly selected element into     * the "current position".  Elements are randomly selected from the     * portion of the list that runs from the first element to the current     * position, inclusive.<p>     *     * This method runs in linear time.  If the specified list does not     * implement the {@link RandomAccess} interface and is large, this     * implementation dumps the specified list into an array before shuffling     * it, and dumps the shuffled array back into the list.  This avoids the     * quadratic behavior that would result from shuffling a "sequential     * access" list in place.     *     * @param  list the list to be shuffled.     * @param  rnd the source of randomness to use to shuffle the list.     * @throws UnsupportedOperationException if the specified list or its     *         list-iterator does not support the <tt>set</tt> operation.     */    public static void shuffle(List<?> list, Random rnd) {        int size = list.size();        if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {            for (int i=size; i>1; i--)                swap(list, i-1, rnd.nextInt(i));

Lines 1–500 of 3966.