emul/compact/src/main/java/java/util/AbstractCollection.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 23 Jan 2013 22:32:27 +0100
branchjdk7-b147
changeset 557 5be31d9fa455
permissions -rw-r--r--
Basic classes needed to support ServiceLoader
     1 /*
     2  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.util;
    27 
    28 /**
    29  * This class provides a skeletal implementation of the <tt>Collection</tt>
    30  * interface, to minimize the effort required to implement this interface. <p>
    31  *
    32  * To implement an unmodifiable collection, the programmer needs only to
    33  * extend this class and provide implementations for the <tt>iterator</tt> and
    34  * <tt>size</tt> methods.  (The iterator returned by the <tt>iterator</tt>
    35  * method must implement <tt>hasNext</tt> and <tt>next</tt>.)<p>
    36  *
    37  * To implement a modifiable collection, the programmer must additionally
    38  * override this class's <tt>add</tt> method (which otherwise throws an
    39  * <tt>UnsupportedOperationException</tt>), and the iterator returned by the
    40  * <tt>iterator</tt> method must additionally implement its <tt>remove</tt>
    41  * method.<p>
    42  *
    43  * The programmer should generally provide a void (no argument) and
    44  * <tt>Collection</tt> constructor, as per the recommendation in the
    45  * <tt>Collection</tt> interface specification.<p>
    46  *
    47  * The documentation for each non-abstract method in this class describes its
    48  * implementation in detail.  Each of these methods may be overridden if
    49  * the collection being implemented admits a more efficient implementation.<p>
    50  *
    51  * This class is a member of the
    52  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
    53  * Java Collections Framework</a>.
    54  *
    55  * @author  Josh Bloch
    56  * @author  Neal Gafter
    57  * @see Collection
    58  * @since 1.2
    59  */
    60 
    61 public abstract class AbstractCollection<E> implements Collection<E> {
    62     /**
    63      * Sole constructor.  (For invocation by subclass constructors, typically
    64      * implicit.)
    65      */
    66     protected AbstractCollection() {
    67     }
    68 
    69     // Query Operations
    70 
    71     /**
    72      * Returns an iterator over the elements contained in this collection.
    73      *
    74      * @return an iterator over the elements contained in this collection
    75      */
    76     public abstract Iterator<E> iterator();
    77 
    78     public abstract int size();
    79 
    80     /**
    81      * {@inheritDoc}
    82      *
    83      * <p>This implementation returns <tt>size() == 0</tt>.
    84      */
    85     public boolean isEmpty() {
    86         return size() == 0;
    87     }
    88 
    89     /**
    90      * {@inheritDoc}
    91      *
    92      * <p>This implementation iterates over the elements in the collection,
    93      * checking each element in turn for equality with the specified element.
    94      *
    95      * @throws ClassCastException   {@inheritDoc}
    96      * @throws NullPointerException {@inheritDoc}
    97      */
    98     public boolean contains(Object o) {
    99         Iterator<E> it = iterator();
   100         if (o==null) {
   101             while (it.hasNext())
   102                 if (it.next()==null)
   103                     return true;
   104         } else {
   105             while (it.hasNext())
   106                 if (o.equals(it.next()))
   107                     return true;
   108         }
   109         return false;
   110     }
   111 
   112     /**
   113      * {@inheritDoc}
   114      *
   115      * <p>This implementation returns an array containing all the elements
   116      * returned by this collection's iterator, in the same order, stored in
   117      * consecutive elements of the array, starting with index {@code 0}.
   118      * The length of the returned array is equal to the number of elements
   119      * returned by the iterator, even if the size of this collection changes
   120      * during iteration, as might happen if the collection permits
   121      * concurrent modification during iteration.  The {@code size} method is
   122      * called only as an optimization hint; the correct result is returned
   123      * even if the iterator returns a different number of elements.
   124      *
   125      * <p>This method is equivalent to:
   126      *
   127      *  <pre> {@code
   128      * List<E> list = new ArrayList<E>(size());
   129      * for (E e : this)
   130      *     list.add(e);
   131      * return list.toArray();
   132      * }</pre>
   133      */
   134     public Object[] toArray() {
   135         // Estimate size of array; be prepared to see more or fewer elements
   136         Object[] r = new Object[size()];
   137         Iterator<E> it = iterator();
   138         for (int i = 0; i < r.length; i++) {
   139             if (! it.hasNext()) // fewer elements than expected
   140                 return Arrays.copyOf(r, i);
   141             r[i] = it.next();
   142         }
   143         return it.hasNext() ? finishToArray(r, it) : r;
   144     }
   145 
   146     /**
   147      * {@inheritDoc}
   148      *
   149      * <p>This implementation returns an array containing all the elements
   150      * returned by this collection's iterator in the same order, stored in
   151      * consecutive elements of the array, starting with index {@code 0}.
   152      * If the number of elements returned by the iterator is too large to
   153      * fit into the specified array, then the elements are returned in a
   154      * newly allocated array with length equal to the number of elements
   155      * returned by the iterator, even if the size of this collection
   156      * changes during iteration, as might happen if the collection permits
   157      * concurrent modification during iteration.  The {@code size} method is
   158      * called only as an optimization hint; the correct result is returned
   159      * even if the iterator returns a different number of elements.
   160      *
   161      * <p>This method is equivalent to:
   162      *
   163      *  <pre> {@code
   164      * List<E> list = new ArrayList<E>(size());
   165      * for (E e : this)
   166      *     list.add(e);
   167      * return list.toArray(a);
   168      * }</pre>
   169      *
   170      * @throws ArrayStoreException  {@inheritDoc}
   171      * @throws NullPointerException {@inheritDoc}
   172      */
   173     public <T> T[] toArray(T[] a) {
   174         // Estimate size of array; be prepared to see more or fewer elements
   175         int size = size();
   176         T[] r = a.length >= size ? a :
   177                   (T[])java.lang.reflect.Array
   178                   .newInstance(a.getClass().getComponentType(), size);
   179         Iterator<E> it = iterator();
   180 
   181         for (int i = 0; i < r.length; i++) {
   182             if (! it.hasNext()) { // fewer elements than expected
   183                 if (a != r)
   184                     return Arrays.copyOf(r, i);
   185                 r[i] = null; // null-terminate
   186                 return r;
   187             }
   188             r[i] = (T)it.next();
   189         }
   190         return it.hasNext() ? finishToArray(r, it) : r;
   191     }
   192 
   193     /**
   194      * The maximum size of array to allocate.
   195      * Some VMs reserve some header words in an array.
   196      * Attempts to allocate larger arrays may result in
   197      * OutOfMemoryError: Requested array size exceeds VM limit
   198      */
   199     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
   200 
   201     /**
   202      * Reallocates the array being used within toArray when the iterator
   203      * returned more elements than expected, and finishes filling it from
   204      * the iterator.
   205      *
   206      * @param r the array, replete with previously stored elements
   207      * @param it the in-progress iterator over this collection
   208      * @return array containing the elements in the given array, plus any
   209      *         further elements returned by the iterator, trimmed to size
   210      */
   211     private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
   212         int i = r.length;
   213         while (it.hasNext()) {
   214             int cap = r.length;
   215             if (i == cap) {
   216                 int newCap = cap + (cap >> 1) + 1;
   217                 // overflow-conscious code
   218                 if (newCap - MAX_ARRAY_SIZE > 0)
   219                     newCap = hugeCapacity(cap + 1);
   220                 r = Arrays.copyOf(r, newCap);
   221             }
   222             r[i++] = (T)it.next();
   223         }
   224         // trim if overallocated
   225         return (i == r.length) ? r : Arrays.copyOf(r, i);
   226     }
   227 
   228     private static int hugeCapacity(int minCapacity) {
   229         if (minCapacity < 0) // overflow
   230             throw new OutOfMemoryError
   231                 ("Required array size too large");
   232         return (minCapacity > MAX_ARRAY_SIZE) ?
   233             Integer.MAX_VALUE :
   234             MAX_ARRAY_SIZE;
   235     }
   236 
   237     // Modification Operations
   238 
   239     /**
   240      * {@inheritDoc}
   241      *
   242      * <p>This implementation always throws an
   243      * <tt>UnsupportedOperationException</tt>.
   244      *
   245      * @throws UnsupportedOperationException {@inheritDoc}
   246      * @throws ClassCastException            {@inheritDoc}
   247      * @throws NullPointerException          {@inheritDoc}
   248      * @throws IllegalArgumentException      {@inheritDoc}
   249      * @throws IllegalStateException         {@inheritDoc}
   250      */
   251     public boolean add(E e) {
   252         throw new UnsupportedOperationException();
   253     }
   254 
   255     /**
   256      * {@inheritDoc}
   257      *
   258      * <p>This implementation iterates over the collection looking for the
   259      * specified element.  If it finds the element, it removes the element
   260      * from the collection using the iterator's remove method.
   261      *
   262      * <p>Note that this implementation throws an
   263      * <tt>UnsupportedOperationException</tt> if the iterator returned by this
   264      * collection's iterator method does not implement the <tt>remove</tt>
   265      * method and this collection contains the specified object.
   266      *
   267      * @throws UnsupportedOperationException {@inheritDoc}
   268      * @throws ClassCastException            {@inheritDoc}
   269      * @throws NullPointerException          {@inheritDoc}
   270      */
   271     public boolean remove(Object o) {
   272         Iterator<E> it = iterator();
   273         if (o==null) {
   274             while (it.hasNext()) {
   275                 if (it.next()==null) {
   276                     it.remove();
   277                     return true;
   278                 }
   279             }
   280         } else {
   281             while (it.hasNext()) {
   282                 if (o.equals(it.next())) {
   283                     it.remove();
   284                     return true;
   285                 }
   286             }
   287         }
   288         return false;
   289     }
   290 
   291 
   292     // Bulk Operations
   293 
   294     /**
   295      * {@inheritDoc}
   296      *
   297      * <p>This implementation iterates over the specified collection,
   298      * checking each element returned by the iterator in turn to see
   299      * if it's contained in this collection.  If all elements are so
   300      * contained <tt>true</tt> is returned, otherwise <tt>false</tt>.
   301      *
   302      * @throws ClassCastException            {@inheritDoc}
   303      * @throws NullPointerException          {@inheritDoc}
   304      * @see #contains(Object)
   305      */
   306     public boolean containsAll(Collection<?> c) {
   307         for (Object e : c)
   308             if (!contains(e))
   309                 return false;
   310         return true;
   311     }
   312 
   313     /**
   314      * {@inheritDoc}
   315      *
   316      * <p>This implementation iterates over the specified collection, and adds
   317      * each object returned by the iterator to this collection, in turn.
   318      *
   319      * <p>Note that this implementation will throw an
   320      * <tt>UnsupportedOperationException</tt> unless <tt>add</tt> is
   321      * overridden (assuming the specified collection is non-empty).
   322      *
   323      * @throws UnsupportedOperationException {@inheritDoc}
   324      * @throws ClassCastException            {@inheritDoc}
   325      * @throws NullPointerException          {@inheritDoc}
   326      * @throws IllegalArgumentException      {@inheritDoc}
   327      * @throws IllegalStateException         {@inheritDoc}
   328      *
   329      * @see #add(Object)
   330      */
   331     public boolean addAll(Collection<? extends E> c) {
   332         boolean modified = false;
   333         for (E e : c)
   334             if (add(e))
   335                 modified = true;
   336         return modified;
   337     }
   338 
   339     /**
   340      * {@inheritDoc}
   341      *
   342      * <p>This implementation iterates over this collection, checking each
   343      * element returned by the iterator in turn to see if it's contained
   344      * in the specified collection.  If it's so contained, it's removed from
   345      * this collection with the iterator's <tt>remove</tt> method.
   346      *
   347      * <p>Note that this implementation will throw an
   348      * <tt>UnsupportedOperationException</tt> if the iterator returned by the
   349      * <tt>iterator</tt> method does not implement the <tt>remove</tt> method
   350      * and this collection contains one or more elements in common with the
   351      * specified collection.
   352      *
   353      * @throws UnsupportedOperationException {@inheritDoc}
   354      * @throws ClassCastException            {@inheritDoc}
   355      * @throws NullPointerException          {@inheritDoc}
   356      *
   357      * @see #remove(Object)
   358      * @see #contains(Object)
   359      */
   360     public boolean removeAll(Collection<?> c) {
   361         boolean modified = false;
   362         Iterator<?> it = iterator();
   363         while (it.hasNext()) {
   364             if (c.contains(it.next())) {
   365                 it.remove();
   366                 modified = true;
   367             }
   368         }
   369         return modified;
   370     }
   371 
   372     /**
   373      * {@inheritDoc}
   374      *
   375      * <p>This implementation iterates over this collection, checking each
   376      * element returned by the iterator in turn to see if it's contained
   377      * in the specified collection.  If it's not so contained, it's removed
   378      * from this collection with the iterator's <tt>remove</tt> method.
   379      *
   380      * <p>Note that this implementation will throw an
   381      * <tt>UnsupportedOperationException</tt> if the iterator returned by the
   382      * <tt>iterator</tt> method does not implement the <tt>remove</tt> method
   383      * and this collection contains one or more elements not present in the
   384      * specified collection.
   385      *
   386      * @throws UnsupportedOperationException {@inheritDoc}
   387      * @throws ClassCastException            {@inheritDoc}
   388      * @throws NullPointerException          {@inheritDoc}
   389      *
   390      * @see #remove(Object)
   391      * @see #contains(Object)
   392      */
   393     public boolean retainAll(Collection<?> c) {
   394         boolean modified = false;
   395         Iterator<E> it = iterator();
   396         while (it.hasNext()) {
   397             if (!c.contains(it.next())) {
   398                 it.remove();
   399                 modified = true;
   400             }
   401         }
   402         return modified;
   403     }
   404 
   405     /**
   406      * {@inheritDoc}
   407      *
   408      * <p>This implementation iterates over this collection, removing each
   409      * element using the <tt>Iterator.remove</tt> operation.  Most
   410      * implementations will probably choose to override this method for
   411      * efficiency.
   412      *
   413      * <p>Note that this implementation will throw an
   414      * <tt>UnsupportedOperationException</tt> if the iterator returned by this
   415      * collection's <tt>iterator</tt> method does not implement the
   416      * <tt>remove</tt> method and this collection is non-empty.
   417      *
   418      * @throws UnsupportedOperationException {@inheritDoc}
   419      */
   420     public void clear() {
   421         Iterator<E> it = iterator();
   422         while (it.hasNext()) {
   423             it.next();
   424             it.remove();
   425         }
   426     }
   427 
   428 
   429     //  String conversion
   430 
   431     /**
   432      * Returns a string representation of this collection.  The string
   433      * representation consists of a list of the collection's elements in the
   434      * order they are returned by its iterator, enclosed in square brackets
   435      * (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
   436      * <tt>", "</tt> (comma and space).  Elements are converted to strings as
   437      * by {@link String#valueOf(Object)}.
   438      *
   439      * @return a string representation of this collection
   440      */
   441     public String toString() {
   442         Iterator<E> it = iterator();
   443         if (! it.hasNext())
   444             return "[]";
   445 
   446         StringBuilder sb = new StringBuilder();
   447         sb.append('[');
   448         for (;;) {
   449             E e = it.next();
   450             sb.append(e == this ? "(this Collection)" : e);
   451             if (! it.hasNext())
   452                 return sb.append(']').toString();
   453             sb.append(',').append(' ');
   454         }
   455     }
   456 
   457 }