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