emul/compact/src/main/java/java/util/ArrayList.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 23 Jan 2013 22:55:28 +0100
branchemul
changeset 560 53fafe384803
parent 557 5be31d9fa455
child 636 8d0be6a9a809
permissions -rw-r--r--
Moving all arraycopy methods into one System class
     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 import org.apidesign.bck2brwsr.emul.lang.System;
    29 
    30 /**
    31  * Resizable-array implementation of the <tt>List</tt> interface.  Implements
    32  * all optional list operations, and permits all elements, including
    33  * <tt>null</tt>.  In addition to implementing the <tt>List</tt> interface,
    34  * this class provides methods to manipulate the size of the array that is
    35  * used internally to store the list.  (This class is roughly equivalent to
    36  * <tt>Vector</tt>, except that it is unsynchronized.)
    37  *
    38  * <p>The <tt>size</tt>, <tt>isEmpty</tt>, <tt>get</tt>, <tt>set</tt>,
    39  * <tt>iterator</tt>, and <tt>listIterator</tt> operations run in constant
    40  * time.  The <tt>add</tt> operation runs in <i>amortized constant time</i>,
    41  * that is, adding n elements requires O(n) time.  All of the other operations
    42  * run in linear time (roughly speaking).  The constant factor is low compared
    43  * to that for the <tt>LinkedList</tt> implementation.
    44  *
    45  * <p>Each <tt>ArrayList</tt> instance has a <i>capacity</i>.  The capacity is
    46  * the size of the array used to store the elements in the list.  It is always
    47  * at least as large as the list size.  As elements are added to an ArrayList,
    48  * its capacity grows automatically.  The details of the growth policy are not
    49  * specified beyond the fact that adding an element has constant amortized
    50  * time cost.
    51  *
    52  * <p>An application can increase the capacity of an <tt>ArrayList</tt> instance
    53  * before adding a large number of elements using the <tt>ensureCapacity</tt>
    54  * operation.  This may reduce the amount of incremental reallocation.
    55  *
    56  * <p><strong>Note that this implementation is not synchronized.</strong>
    57  * If multiple threads access an <tt>ArrayList</tt> instance concurrently,
    58  * and at least one of the threads modifies the list structurally, it
    59  * <i>must</i> be synchronized externally.  (A structural modification is
    60  * any operation that adds or deletes one or more elements, or explicitly
    61  * resizes the backing array; merely setting the value of an element is not
    62  * a structural modification.)  This is typically accomplished by
    63  * synchronizing on some object that naturally encapsulates the list.
    64  *
    65  * If no such object exists, the list should be "wrapped" using the
    66  * {@link Collections#synchronizedList Collections.synchronizedList}
    67  * method.  This is best done at creation time, to prevent accidental
    68  * unsynchronized access to the list:<pre>
    69  *   List list = Collections.synchronizedList(new ArrayList(...));</pre>
    70  *
    71  * <p><a name="fail-fast"/>
    72  * The iterators returned by this class's {@link #iterator() iterator} and
    73  * {@link #listIterator(int) listIterator} methods are <em>fail-fast</em>:
    74  * if the list is structurally modified at any time after the iterator is
    75  * created, in any way except through the iterator's own
    76  * {@link ListIterator#remove() remove} or
    77  * {@link ListIterator#add(Object) add} methods, the iterator will throw a
    78  * {@link ConcurrentModificationException}.  Thus, in the face of
    79  * concurrent modification, the iterator fails quickly and cleanly, rather
    80  * than risking arbitrary, non-deterministic behavior at an undetermined
    81  * time in the future.
    82  *
    83  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
    84  * as it is, generally speaking, impossible to make any hard guarantees in the
    85  * presence of unsynchronized concurrent modification.  Fail-fast iterators
    86  * throw {@code ConcurrentModificationException} on a best-effort basis.
    87  * Therefore, it would be wrong to write a program that depended on this
    88  * exception for its correctness:  <i>the fail-fast behavior of iterators
    89  * should be used only to detect bugs.</i>
    90  *
    91  * <p>This class is a member of the
    92  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
    93  * Java Collections Framework</a>.
    94  *
    95  * @author  Josh Bloch
    96  * @author  Neal Gafter
    97  * @see     Collection
    98  * @see     List
    99  * @see     LinkedList
   100  * @see     Vector
   101  * @since   1.2
   102  */
   103 
   104 public class ArrayList<E> extends AbstractList<E>
   105         implements List<E>, RandomAccess, Cloneable, java.io.Serializable
   106 {
   107     private static final long serialVersionUID = 8683452581122892189L;
   108 
   109     /**
   110      * The array buffer into which the elements of the ArrayList are stored.
   111      * The capacity of the ArrayList is the length of this array buffer.
   112      */
   113     private transient Object[] elementData;
   114 
   115     /**
   116      * The size of the ArrayList (the number of elements it contains).
   117      *
   118      * @serial
   119      */
   120     private int size;
   121 
   122     /**
   123      * Constructs an empty list with the specified initial capacity.
   124      *
   125      * @param  initialCapacity  the initial capacity of the list
   126      * @throws IllegalArgumentException if the specified initial capacity
   127      *         is negative
   128      */
   129     public ArrayList(int initialCapacity) {
   130         super();
   131         if (initialCapacity < 0)
   132             throw new IllegalArgumentException("Illegal Capacity: "+
   133                                                initialCapacity);
   134         this.elementData = new Object[initialCapacity];
   135     }
   136 
   137     /**
   138      * Constructs an empty list with an initial capacity of ten.
   139      */
   140     public ArrayList() {
   141         this(10);
   142     }
   143 
   144     /**
   145      * Constructs a list containing the elements of the specified
   146      * collection, in the order they are returned by the collection's
   147      * iterator.
   148      *
   149      * @param c the collection whose elements are to be placed into this list
   150      * @throws NullPointerException if the specified collection is null
   151      */
   152     public ArrayList(Collection<? extends E> c) {
   153         elementData = c.toArray();
   154         size = elementData.length;
   155         // c.toArray might (incorrectly) not return Object[] (see 6260652)
   156         if (elementData.getClass() != Object[].class)
   157             elementData = Arrays.copyOf(elementData, size, Object[].class);
   158     }
   159 
   160     /**
   161      * Trims the capacity of this <tt>ArrayList</tt> instance to be the
   162      * list's current size.  An application can use this operation to minimize
   163      * the storage of an <tt>ArrayList</tt> instance.
   164      */
   165     public void trimToSize() {
   166         modCount++;
   167         int oldCapacity = elementData.length;
   168         if (size < oldCapacity) {
   169             elementData = Arrays.copyOf(elementData, size);
   170         }
   171     }
   172 
   173     /**
   174      * Increases the capacity of this <tt>ArrayList</tt> instance, if
   175      * necessary, to ensure that it can hold at least the number of elements
   176      * specified by the minimum capacity argument.
   177      *
   178      * @param   minCapacity   the desired minimum capacity
   179      */
   180     public void ensureCapacity(int minCapacity) {
   181         if (minCapacity > 0)
   182             ensureCapacityInternal(minCapacity);
   183     }
   184 
   185     private void ensureCapacityInternal(int minCapacity) {
   186         modCount++;
   187         // overflow-conscious code
   188         if (minCapacity - elementData.length > 0)
   189             grow(minCapacity);
   190     }
   191 
   192     /**
   193      * The maximum size of array to allocate.
   194      * Some VMs reserve some header words in an array.
   195      * Attempts to allocate larger arrays may result in
   196      * OutOfMemoryError: Requested array size exceeds VM limit
   197      */
   198     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
   199 
   200     /**
   201      * Increases the capacity to ensure that it can hold at least the
   202      * number of elements specified by the minimum capacity argument.
   203      *
   204      * @param minCapacity the desired minimum capacity
   205      */
   206     private void grow(int minCapacity) {
   207         // overflow-conscious code
   208         int oldCapacity = elementData.length;
   209         int newCapacity = oldCapacity + (oldCapacity >> 1);
   210         if (newCapacity - minCapacity < 0)
   211             newCapacity = minCapacity;
   212         if (newCapacity - MAX_ARRAY_SIZE > 0)
   213             newCapacity = hugeCapacity(minCapacity);
   214         // minCapacity is usually close to size, so this is a win:
   215         elementData = Arrays.copyOf(elementData, newCapacity);
   216     }
   217 
   218     private static int hugeCapacity(int minCapacity) {
   219         if (minCapacity < 0) // overflow
   220             throw new OutOfMemoryError();
   221         return (minCapacity > MAX_ARRAY_SIZE) ?
   222             Integer.MAX_VALUE :
   223             MAX_ARRAY_SIZE;
   224     }
   225 
   226     /**
   227      * Returns the number of elements in this list.
   228      *
   229      * @return the number of elements in this list
   230      */
   231     public int size() {
   232         return size;
   233     }
   234 
   235     /**
   236      * Returns <tt>true</tt> if this list contains no elements.
   237      *
   238      * @return <tt>true</tt> if this list contains no elements
   239      */
   240     public boolean isEmpty() {
   241         return size == 0;
   242     }
   243 
   244     /**
   245      * Returns <tt>true</tt> if this list contains the specified element.
   246      * More formally, returns <tt>true</tt> if and only if this list contains
   247      * at least one element <tt>e</tt> such that
   248      * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
   249      *
   250      * @param o element whose presence in this list is to be tested
   251      * @return <tt>true</tt> if this list contains the specified element
   252      */
   253     public boolean contains(Object o) {
   254         return indexOf(o) >= 0;
   255     }
   256 
   257     /**
   258      * Returns the index of the first occurrence of the specified element
   259      * in this list, or -1 if this list does not contain the element.
   260      * More formally, returns the lowest index <tt>i</tt> such that
   261      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
   262      * or -1 if there is no such index.
   263      */
   264     public int indexOf(Object o) {
   265         if (o == null) {
   266             for (int i = 0; i < size; i++)
   267                 if (elementData[i]==null)
   268                     return i;
   269         } else {
   270             for (int i = 0; i < size; i++)
   271                 if (o.equals(elementData[i]))
   272                     return i;
   273         }
   274         return -1;
   275     }
   276 
   277     /**
   278      * Returns the index of the last occurrence of the specified element
   279      * in this list, or -1 if this list does not contain the element.
   280      * More formally, returns the highest index <tt>i</tt> such that
   281      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
   282      * or -1 if there is no such index.
   283      */
   284     public int lastIndexOf(Object o) {
   285         if (o == null) {
   286             for (int i = size-1; i >= 0; i--)
   287                 if (elementData[i]==null)
   288                     return i;
   289         } else {
   290             for (int i = size-1; i >= 0; i--)
   291                 if (o.equals(elementData[i]))
   292                     return i;
   293         }
   294         return -1;
   295     }
   296 
   297     /**
   298      * Returns a shallow copy of this <tt>ArrayList</tt> instance.  (The
   299      * elements themselves are not copied.)
   300      *
   301      * @return a clone of this <tt>ArrayList</tt> instance
   302      */
   303     public Object clone() {
   304         try {
   305             @SuppressWarnings("unchecked")
   306                 ArrayList<E> v = (ArrayList<E>) super.clone();
   307             v.elementData = Arrays.copyOf(elementData, size);
   308             v.modCount = 0;
   309             return v;
   310         } catch (CloneNotSupportedException e) {
   311             // this shouldn't happen, since we are Cloneable
   312             throw new InternalError();
   313         }
   314     }
   315 
   316     /**
   317      * Returns an array containing all of the elements in this list
   318      * in proper sequence (from first to last element).
   319      *
   320      * <p>The returned array will be "safe" in that no references to it are
   321      * maintained by this list.  (In other words, this method must allocate
   322      * a new array).  The caller is thus free to modify the returned array.
   323      *
   324      * <p>This method acts as bridge between array-based and collection-based
   325      * APIs.
   326      *
   327      * @return an array containing all of the elements in this list in
   328      *         proper sequence
   329      */
   330     public Object[] toArray() {
   331         return Arrays.copyOf(elementData, size);
   332     }
   333 
   334     /**
   335      * Returns an array containing all of the elements in this list in proper
   336      * sequence (from first to last element); the runtime type of the returned
   337      * array is that of the specified array.  If the list fits in the
   338      * specified array, it is returned therein.  Otherwise, a new array is
   339      * allocated with the runtime type of the specified array and the size of
   340      * this list.
   341      *
   342      * <p>If the list fits in the specified array with room to spare
   343      * (i.e., the array has more elements than the list), the element in
   344      * the array immediately following the end of the collection is set to
   345      * <tt>null</tt>.  (This is useful in determining the length of the
   346      * list <i>only</i> if the caller knows that the list does not contain
   347      * any null elements.)
   348      *
   349      * @param a the array into which the elements of the list are to
   350      *          be stored, if it is big enough; otherwise, a new array of the
   351      *          same runtime type is allocated for this purpose.
   352      * @return an array containing the elements of the list
   353      * @throws ArrayStoreException if the runtime type of the specified array
   354      *         is not a supertype of the runtime type of every element in
   355      *         this list
   356      * @throws NullPointerException if the specified array is null
   357      */
   358     @SuppressWarnings("unchecked")
   359     public <T> T[] toArray(T[] a) {
   360         if (a.length < size)
   361             // Make a new array of a's runtime type, but my contents:
   362             return (T[]) Arrays.copyOf(elementData, size, a.getClass());
   363         System.arraycopy(elementData, 0, a, 0, size);
   364         if (a.length > size)
   365             a[size] = null;
   366         return a;
   367     }
   368 
   369     // Positional Access Operations
   370 
   371     @SuppressWarnings("unchecked")
   372     E elementData(int index) {
   373         return (E) elementData[index];
   374     }
   375 
   376     /**
   377      * Returns the element at the specified position in this list.
   378      *
   379      * @param  index index of the element to return
   380      * @return the element at the specified position in this list
   381      * @throws IndexOutOfBoundsException {@inheritDoc}
   382      */
   383     public E get(int index) {
   384         rangeCheck(index);
   385 
   386         return elementData(index);
   387     }
   388 
   389     /**
   390      * Replaces the element at the specified position in this list with
   391      * the specified element.
   392      *
   393      * @param index index of the element to replace
   394      * @param element element to be stored at the specified position
   395      * @return the element previously at the specified position
   396      * @throws IndexOutOfBoundsException {@inheritDoc}
   397      */
   398     public E set(int index, E element) {
   399         rangeCheck(index);
   400 
   401         E oldValue = elementData(index);
   402         elementData[index] = element;
   403         return oldValue;
   404     }
   405 
   406     /**
   407      * Appends the specified element to the end of this list.
   408      *
   409      * @param e element to be appended to this list
   410      * @return <tt>true</tt> (as specified by {@link Collection#add})
   411      */
   412     public boolean add(E e) {
   413         ensureCapacityInternal(size + 1);  // Increments modCount!!
   414         elementData[size++] = e;
   415         return true;
   416     }
   417 
   418     /**
   419      * Inserts the specified element at the specified position in this
   420      * list. Shifts the element currently at that position (if any) and
   421      * any subsequent elements to the right (adds one to their indices).
   422      *
   423      * @param index index at which the specified element is to be inserted
   424      * @param element element to be inserted
   425      * @throws IndexOutOfBoundsException {@inheritDoc}
   426      */
   427     public void add(int index, E element) {
   428         rangeCheckForAdd(index);
   429 
   430         ensureCapacityInternal(size + 1);  // Increments modCount!!
   431         System.arraycopy(elementData, index, elementData, index + 1,
   432                          size - index);
   433         elementData[index] = element;
   434         size++;
   435     }
   436 
   437     /**
   438      * Removes the element at the specified position in this list.
   439      * Shifts any subsequent elements to the left (subtracts one from their
   440      * indices).
   441      *
   442      * @param index the index of the element to be removed
   443      * @return the element that was removed from the list
   444      * @throws IndexOutOfBoundsException {@inheritDoc}
   445      */
   446     public E remove(int index) {
   447         rangeCheck(index);
   448 
   449         modCount++;
   450         E oldValue = elementData(index);
   451 
   452         int numMoved = size - index - 1;
   453         if (numMoved > 0)
   454             System.arraycopy(elementData, index+1, elementData, index,
   455                              numMoved);
   456         elementData[--size] = null; // Let gc do its work
   457 
   458         return oldValue;
   459     }
   460 
   461     /**
   462      * Removes the first occurrence of the specified element from this list,
   463      * if it is present.  If the list does not contain the element, it is
   464      * unchanged.  More formally, removes the element with the lowest index
   465      * <tt>i</tt> such that
   466      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
   467      * (if such an element exists).  Returns <tt>true</tt> if this list
   468      * contained the specified element (or equivalently, if this list
   469      * changed as a result of the call).
   470      *
   471      * @param o element to be removed from this list, if present
   472      * @return <tt>true</tt> if this list contained the specified element
   473      */
   474     public boolean remove(Object o) {
   475         if (o == null) {
   476             for (int index = 0; index < size; index++)
   477                 if (elementData[index] == null) {
   478                     fastRemove(index);
   479                     return true;
   480                 }
   481         } else {
   482             for (int index = 0; index < size; index++)
   483                 if (o.equals(elementData[index])) {
   484                     fastRemove(index);
   485                     return true;
   486                 }
   487         }
   488         return false;
   489     }
   490 
   491     /*
   492      * Private remove method that skips bounds checking and does not
   493      * return the value removed.
   494      */
   495     private void fastRemove(int index) {
   496         modCount++;
   497         int numMoved = size - index - 1;
   498         if (numMoved > 0)
   499             System.arraycopy(elementData, index+1, elementData, index,
   500                              numMoved);
   501         elementData[--size] = null; // Let gc do its work
   502     }
   503 
   504     /**
   505      * Removes all of the elements from this list.  The list will
   506      * be empty after this call returns.
   507      */
   508     public void clear() {
   509         modCount++;
   510 
   511         // Let gc do its work
   512         for (int i = 0; i < size; i++)
   513             elementData[i] = null;
   514 
   515         size = 0;
   516     }
   517 
   518     /**
   519      * Appends all of the elements in the specified collection to the end of
   520      * this list, in the order that they are returned by the
   521      * specified collection's Iterator.  The behavior of this operation is
   522      * undefined if the specified collection is modified while the operation
   523      * is in progress.  (This implies that the behavior of this call is
   524      * undefined if the specified collection is this list, and this
   525      * list is nonempty.)
   526      *
   527      * @param c collection containing elements to be added to this list
   528      * @return <tt>true</tt> if this list changed as a result of the call
   529      * @throws NullPointerException if the specified collection is null
   530      */
   531     public boolean addAll(Collection<? extends E> c) {
   532         Object[] a = c.toArray();
   533         int numNew = a.length;
   534         ensureCapacityInternal(size + numNew);  // Increments modCount
   535         System.arraycopy(a, 0, elementData, size, numNew);
   536         size += numNew;
   537         return numNew != 0;
   538     }
   539 
   540     /**
   541      * Inserts all of the elements in the specified collection into this
   542      * list, starting at the specified position.  Shifts the element
   543      * currently at that position (if any) and any subsequent elements to
   544      * the right (increases their indices).  The new elements will appear
   545      * in the list in the order that they are returned by the
   546      * specified collection's iterator.
   547      *
   548      * @param index index at which to insert the first element from the
   549      *              specified collection
   550      * @param c collection containing elements to be added to this list
   551      * @return <tt>true</tt> if this list changed as a result of the call
   552      * @throws IndexOutOfBoundsException {@inheritDoc}
   553      * @throws NullPointerException if the specified collection is null
   554      */
   555     public boolean addAll(int index, Collection<? extends E> c) {
   556         rangeCheckForAdd(index);
   557 
   558         Object[] a = c.toArray();
   559         int numNew = a.length;
   560         ensureCapacityInternal(size + numNew);  // Increments modCount
   561 
   562         int numMoved = size - index;
   563         if (numMoved > 0)
   564             System.arraycopy(elementData, index, elementData, index + numNew,
   565                              numMoved);
   566 
   567         System.arraycopy(a, 0, elementData, index, numNew);
   568         size += numNew;
   569         return numNew != 0;
   570     }
   571 
   572     /**
   573      * Removes from this list all of the elements whose index is between
   574      * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
   575      * Shifts any succeeding elements to the left (reduces their index).
   576      * This call shortens the list by {@code (toIndex - fromIndex)} elements.
   577      * (If {@code toIndex==fromIndex}, this operation has no effect.)
   578      *
   579      * @throws IndexOutOfBoundsException if {@code fromIndex} or
   580      *         {@code toIndex} is out of range
   581      *         ({@code fromIndex < 0 ||
   582      *          fromIndex >= size() ||
   583      *          toIndex > size() ||
   584      *          toIndex < fromIndex})
   585      */
   586     protected void removeRange(int fromIndex, int toIndex) {
   587         modCount++;
   588         int numMoved = size - toIndex;
   589         System.arraycopy(elementData, toIndex, elementData, fromIndex,
   590                          numMoved);
   591 
   592         // Let gc do its work
   593         int newSize = size - (toIndex-fromIndex);
   594         while (size != newSize)
   595             elementData[--size] = null;
   596     }
   597 
   598     /**
   599      * Checks if the given index is in range.  If not, throws an appropriate
   600      * runtime exception.  This method does *not* check if the index is
   601      * negative: It is always used immediately prior to an array access,
   602      * which throws an ArrayIndexOutOfBoundsException if index is negative.
   603      */
   604     private void rangeCheck(int index) {
   605         if (index >= size)
   606             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
   607     }
   608 
   609     /**
   610      * A version of rangeCheck used by add and addAll.
   611      */
   612     private void rangeCheckForAdd(int index) {
   613         if (index > size || index < 0)
   614             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
   615     }
   616 
   617     /**
   618      * Constructs an IndexOutOfBoundsException detail message.
   619      * Of the many possible refactorings of the error handling code,
   620      * this "outlining" performs best with both server and client VMs.
   621      */
   622     private String outOfBoundsMsg(int index) {
   623         return "Index: "+index+", Size: "+size;
   624     }
   625 
   626     /**
   627      * Removes from this list all of its elements that are contained in the
   628      * specified collection.
   629      *
   630      * @param c collection containing elements to be removed from this list
   631      * @return {@code true} if this list changed as a result of the call
   632      * @throws ClassCastException if the class of an element of this list
   633      *         is incompatible with the specified collection
   634      * (<a href="Collection.html#optional-restrictions">optional</a>)
   635      * @throws NullPointerException if this list contains a null element and the
   636      *         specified collection does not permit null elements
   637      * (<a href="Collection.html#optional-restrictions">optional</a>),
   638      *         or if the specified collection is null
   639      * @see Collection#contains(Object)
   640      */
   641     public boolean removeAll(Collection<?> c) {
   642         return batchRemove(c, false);
   643     }
   644 
   645     /**
   646      * Retains only the elements in this list that are contained in the
   647      * specified collection.  In other words, removes from this list all
   648      * of its elements that are not contained in the specified collection.
   649      *
   650      * @param c collection containing elements to be retained in this list
   651      * @return {@code true} if this list changed as a result of the call
   652      * @throws ClassCastException if the class of an element of this list
   653      *         is incompatible with the specified collection
   654      * (<a href="Collection.html#optional-restrictions">optional</a>)
   655      * @throws NullPointerException if this list contains a null element and the
   656      *         specified collection does not permit null elements
   657      * (<a href="Collection.html#optional-restrictions">optional</a>),
   658      *         or if the specified collection is null
   659      * @see Collection#contains(Object)
   660      */
   661     public boolean retainAll(Collection<?> c) {
   662         return batchRemove(c, true);
   663     }
   664 
   665     private boolean batchRemove(Collection<?> c, boolean complement) {
   666         final Object[] elementData = this.elementData;
   667         int r = 0, w = 0;
   668         boolean modified = false;
   669         try {
   670             for (; r < size; r++)
   671                 if (c.contains(elementData[r]) == complement)
   672                     elementData[w++] = elementData[r];
   673         } finally {
   674             // Preserve behavioral compatibility with AbstractCollection,
   675             // even if c.contains() throws.
   676             if (r != size) {
   677                 System.arraycopy(elementData, r,
   678                                  elementData, w,
   679                                  size - r);
   680                 w += size - r;
   681             }
   682             if (w != size) {
   683                 for (int i = w; i < size; i++)
   684                     elementData[i] = null;
   685                 modCount += size - w;
   686                 size = w;
   687                 modified = true;
   688             }
   689         }
   690         return modified;
   691     }
   692 
   693     /**
   694      * Returns a list iterator over the elements in this list (in proper
   695      * sequence), starting at the specified position in the list.
   696      * The specified index indicates the first element that would be
   697      * returned by an initial call to {@link ListIterator#next next}.
   698      * An initial call to {@link ListIterator#previous previous} would
   699      * return the element with the specified index minus one.
   700      *
   701      * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
   702      *
   703      * @throws IndexOutOfBoundsException {@inheritDoc}
   704      */
   705     public ListIterator<E> listIterator(int index) {
   706         if (index < 0 || index > size)
   707             throw new IndexOutOfBoundsException("Index: "+index);
   708         return new ListItr(index);
   709     }
   710 
   711     /**
   712      * Returns a list iterator over the elements in this list (in proper
   713      * sequence).
   714      *
   715      * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
   716      *
   717      * @see #listIterator(int)
   718      */
   719     public ListIterator<E> listIterator() {
   720         return new ListItr(0);
   721     }
   722 
   723     /**
   724      * Returns an iterator over the elements in this list in proper sequence.
   725      *
   726      * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
   727      *
   728      * @return an iterator over the elements in this list in proper sequence
   729      */
   730     public Iterator<E> iterator() {
   731         return new Itr();
   732     }
   733 
   734     /**
   735      * An optimized version of AbstractList.Itr
   736      */
   737     private class Itr implements Iterator<E> {
   738         int cursor;       // index of next element to return
   739         int lastRet = -1; // index of last element returned; -1 if no such
   740         int expectedModCount = modCount;
   741 
   742         public boolean hasNext() {
   743             return cursor != size;
   744         }
   745 
   746         @SuppressWarnings("unchecked")
   747         public E next() {
   748             checkForComodification();
   749             int i = cursor;
   750             if (i >= size)
   751                 throw new NoSuchElementException();
   752             Object[] elementData = ArrayList.this.elementData;
   753             if (i >= elementData.length)
   754                 throw new ConcurrentModificationException();
   755             cursor = i + 1;
   756             return (E) elementData[lastRet = i];
   757         }
   758 
   759         public void remove() {
   760             if (lastRet < 0)
   761                 throw new IllegalStateException();
   762             checkForComodification();
   763 
   764             try {
   765                 ArrayList.this.remove(lastRet);
   766                 cursor = lastRet;
   767                 lastRet = -1;
   768                 expectedModCount = modCount;
   769             } catch (IndexOutOfBoundsException ex) {
   770                 throw new ConcurrentModificationException();
   771             }
   772         }
   773 
   774         final void checkForComodification() {
   775             if (modCount != expectedModCount)
   776                 throw new ConcurrentModificationException();
   777         }
   778     }
   779 
   780     /**
   781      * An optimized version of AbstractList.ListItr
   782      */
   783     private class ListItr extends Itr implements ListIterator<E> {
   784         ListItr(int index) {
   785             super();
   786             cursor = index;
   787         }
   788 
   789         public boolean hasPrevious() {
   790             return cursor != 0;
   791         }
   792 
   793         public int nextIndex() {
   794             return cursor;
   795         }
   796 
   797         public int previousIndex() {
   798             return cursor - 1;
   799         }
   800 
   801         @SuppressWarnings("unchecked")
   802         public E previous() {
   803             checkForComodification();
   804             int i = cursor - 1;
   805             if (i < 0)
   806                 throw new NoSuchElementException();
   807             Object[] elementData = ArrayList.this.elementData;
   808             if (i >= elementData.length)
   809                 throw new ConcurrentModificationException();
   810             cursor = i;
   811             return (E) elementData[lastRet = i];
   812         }
   813 
   814         public void set(E e) {
   815             if (lastRet < 0)
   816                 throw new IllegalStateException();
   817             checkForComodification();
   818 
   819             try {
   820                 ArrayList.this.set(lastRet, e);
   821             } catch (IndexOutOfBoundsException ex) {
   822                 throw new ConcurrentModificationException();
   823             }
   824         }
   825 
   826         public void add(E e) {
   827             checkForComodification();
   828 
   829             try {
   830                 int i = cursor;
   831                 ArrayList.this.add(i, e);
   832                 cursor = i + 1;
   833                 lastRet = -1;
   834                 expectedModCount = modCount;
   835             } catch (IndexOutOfBoundsException ex) {
   836                 throw new ConcurrentModificationException();
   837             }
   838         }
   839     }
   840 
   841     /**
   842      * Returns a view of the portion of this list between the specified
   843      * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.  (If
   844      * {@code fromIndex} and {@code toIndex} are equal, the returned list is
   845      * empty.)  The returned list is backed by this list, so non-structural
   846      * changes in the returned list are reflected in this list, and vice-versa.
   847      * The returned list supports all of the optional list operations.
   848      *
   849      * <p>This method eliminates the need for explicit range operations (of
   850      * the sort that commonly exist for arrays).  Any operation that expects
   851      * a list can be used as a range operation by passing a subList view
   852      * instead of a whole list.  For example, the following idiom
   853      * removes a range of elements from a list:
   854      * <pre>
   855      *      list.subList(from, to).clear();
   856      * </pre>
   857      * Similar idioms may be constructed for {@link #indexOf(Object)} and
   858      * {@link #lastIndexOf(Object)}, and all of the algorithms in the
   859      * {@link Collections} class can be applied to a subList.
   860      *
   861      * <p>The semantics of the list returned by this method become undefined if
   862      * the backing list (i.e., this list) is <i>structurally modified</i> in
   863      * any way other than via the returned list.  (Structural modifications are
   864      * those that change the size of this list, or otherwise perturb it in such
   865      * a fashion that iterations in progress may yield incorrect results.)
   866      *
   867      * @throws IndexOutOfBoundsException {@inheritDoc}
   868      * @throws IllegalArgumentException {@inheritDoc}
   869      */
   870     public List<E> subList(int fromIndex, int toIndex) {
   871         subListRangeCheck(fromIndex, toIndex, size);
   872         return new SubList(this, 0, fromIndex, toIndex);
   873     }
   874 
   875     static void subListRangeCheck(int fromIndex, int toIndex, int size) {
   876         if (fromIndex < 0)
   877             throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
   878         if (toIndex > size)
   879             throw new IndexOutOfBoundsException("toIndex = " + toIndex);
   880         if (fromIndex > toIndex)
   881             throw new IllegalArgumentException("fromIndex(" + fromIndex +
   882                                                ") > toIndex(" + toIndex + ")");
   883     }
   884 
   885     private class SubList extends AbstractList<E> implements RandomAccess {
   886         private final AbstractList<E> parent;
   887         private final int parentOffset;
   888         private final int offset;
   889         int size;
   890 
   891         SubList(AbstractList<E> parent,
   892                 int offset, int fromIndex, int toIndex) {
   893             this.parent = parent;
   894             this.parentOffset = fromIndex;
   895             this.offset = offset + fromIndex;
   896             this.size = toIndex - fromIndex;
   897             this.modCount = ArrayList.this.modCount;
   898         }
   899 
   900         public E set(int index, E e) {
   901             rangeCheck(index);
   902             checkForComodification();
   903             E oldValue = ArrayList.this.elementData(offset + index);
   904             ArrayList.this.elementData[offset + index] = e;
   905             return oldValue;
   906         }
   907 
   908         public E get(int index) {
   909             rangeCheck(index);
   910             checkForComodification();
   911             return ArrayList.this.elementData(offset + index);
   912         }
   913 
   914         public int size() {
   915             checkForComodification();
   916             return this.size;
   917         }
   918 
   919         public void add(int index, E e) {
   920             rangeCheckForAdd(index);
   921             checkForComodification();
   922             parent.add(parentOffset + index, e);
   923             this.modCount = parent.modCount;
   924             this.size++;
   925         }
   926 
   927         public E remove(int index) {
   928             rangeCheck(index);
   929             checkForComodification();
   930             E result = parent.remove(parentOffset + index);
   931             this.modCount = parent.modCount;
   932             this.size--;
   933             return result;
   934         }
   935 
   936         protected void removeRange(int fromIndex, int toIndex) {
   937             checkForComodification();
   938             parent.removeRange(parentOffset + fromIndex,
   939                                parentOffset + toIndex);
   940             this.modCount = parent.modCount;
   941             this.size -= toIndex - fromIndex;
   942         }
   943 
   944         public boolean addAll(Collection<? extends E> c) {
   945             return addAll(this.size, c);
   946         }
   947 
   948         public boolean addAll(int index, Collection<? extends E> c) {
   949             rangeCheckForAdd(index);
   950             int cSize = c.size();
   951             if (cSize==0)
   952                 return false;
   953 
   954             checkForComodification();
   955             parent.addAll(parentOffset + index, c);
   956             this.modCount = parent.modCount;
   957             this.size += cSize;
   958             return true;
   959         }
   960 
   961         public Iterator<E> iterator() {
   962             return listIterator();
   963         }
   964 
   965         public ListIterator<E> listIterator(final int index) {
   966             checkForComodification();
   967             rangeCheckForAdd(index);
   968             final int offset = this.offset;
   969 
   970             return new ListIterator<E>() {
   971                 int cursor = index;
   972                 int lastRet = -1;
   973                 int expectedModCount = ArrayList.this.modCount;
   974 
   975                 public boolean hasNext() {
   976                     return cursor != SubList.this.size;
   977                 }
   978 
   979                 @SuppressWarnings("unchecked")
   980                 public E next() {
   981                     checkForComodification();
   982                     int i = cursor;
   983                     if (i >= SubList.this.size)
   984                         throw new NoSuchElementException();
   985                     Object[] elementData = ArrayList.this.elementData;
   986                     if (offset + i >= elementData.length)
   987                         throw new ConcurrentModificationException();
   988                     cursor = i + 1;
   989                     return (E) elementData[offset + (lastRet = i)];
   990                 }
   991 
   992                 public boolean hasPrevious() {
   993                     return cursor != 0;
   994                 }
   995 
   996                 @SuppressWarnings("unchecked")
   997                 public E previous() {
   998                     checkForComodification();
   999                     int i = cursor - 1;
  1000                     if (i < 0)
  1001                         throw new NoSuchElementException();
  1002                     Object[] elementData = ArrayList.this.elementData;
  1003                     if (offset + i >= elementData.length)
  1004                         throw new ConcurrentModificationException();
  1005                     cursor = i;
  1006                     return (E) elementData[offset + (lastRet = i)];
  1007                 }
  1008 
  1009                 public int nextIndex() {
  1010                     return cursor;
  1011                 }
  1012 
  1013                 public int previousIndex() {
  1014                     return cursor - 1;
  1015                 }
  1016 
  1017                 public void remove() {
  1018                     if (lastRet < 0)
  1019                         throw new IllegalStateException();
  1020                     checkForComodification();
  1021 
  1022                     try {
  1023                         SubList.this.remove(lastRet);
  1024                         cursor = lastRet;
  1025                         lastRet = -1;
  1026                         expectedModCount = ArrayList.this.modCount;
  1027                     } catch (IndexOutOfBoundsException ex) {
  1028                         throw new ConcurrentModificationException();
  1029                     }
  1030                 }
  1031 
  1032                 public void set(E e) {
  1033                     if (lastRet < 0)
  1034                         throw new IllegalStateException();
  1035                     checkForComodification();
  1036 
  1037                     try {
  1038                         ArrayList.this.set(offset + lastRet, e);
  1039                     } catch (IndexOutOfBoundsException ex) {
  1040                         throw new ConcurrentModificationException();
  1041                     }
  1042                 }
  1043 
  1044                 public void add(E e) {
  1045                     checkForComodification();
  1046 
  1047                     try {
  1048                         int i = cursor;
  1049                         SubList.this.add(i, e);
  1050                         cursor = i + 1;
  1051                         lastRet = -1;
  1052                         expectedModCount = ArrayList.this.modCount;
  1053                     } catch (IndexOutOfBoundsException ex) {
  1054                         throw new ConcurrentModificationException();
  1055                     }
  1056                 }
  1057 
  1058                 final void checkForComodification() {
  1059                     if (expectedModCount != ArrayList.this.modCount)
  1060                         throw new ConcurrentModificationException();
  1061                 }
  1062             };
  1063         }
  1064 
  1065         public List<E> subList(int fromIndex, int toIndex) {
  1066             subListRangeCheck(fromIndex, toIndex, size);
  1067             return new SubList(this, offset, fromIndex, toIndex);
  1068         }
  1069 
  1070         private void rangeCheck(int index) {
  1071             if (index < 0 || index >= this.size)
  1072                 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  1073         }
  1074 
  1075         private void rangeCheckForAdd(int index) {
  1076             if (index < 0 || index > this.size)
  1077                 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  1078         }
  1079 
  1080         private String outOfBoundsMsg(int index) {
  1081             return "Index: "+index+", Size: "+this.size;
  1082         }
  1083 
  1084         private void checkForComodification() {
  1085             if (ArrayList.this.modCount != this.modCount)
  1086                 throw new ConcurrentModificationException();
  1087         }
  1088     }
  1089 }