Save This Page
Home » openjdk-7 » java » util » [javadoc | source]
    1   /*
    2    * Copyright 1997-2007 Sun Microsystems, Inc.  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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any 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           int oldCapacity = elementData.length;
  181           if (minCapacity > oldCapacity) {
  182               Object oldData[] = elementData;
  183               int newCapacity = (oldCapacity * 3)/2 + 1;
  184               if (newCapacity < minCapacity)
  185                   newCapacity = minCapacity;
  186               // minCapacity is usually close to size, so this is a win:
  187               elementData = Arrays.copyOf(elementData, newCapacity);
  188           }
  189       }
  190   
  191       /**
  192        * Returns the number of elements in this list.
  193        *
  194        * @return the number of elements in this list
  195        */
  196       public int size() {
  197           return size;
  198       }
  199   
  200       /**
  201        * Returns <tt>true</tt> if this list contains no elements.
  202        *
  203        * @return <tt>true</tt> if this list contains no elements
  204        */
  205       public boolean isEmpty() {
  206           return size == 0;
  207       }
  208   
  209       /**
  210        * Returns <tt>true</tt> if this list contains the specified element.
  211        * More formally, returns <tt>true</tt> if and only if this list contains
  212        * at least one element <tt>e</tt> such that
  213        * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
  214        *
  215        * @param o element whose presence in this list is to be tested
  216        * @return <tt>true</tt> if this list contains the specified element
  217        */
  218       public boolean contains(Object o) {
  219           return indexOf(o) >= 0;
  220       }
  221   
  222       /**
  223        * Returns the index of the first occurrence of the specified element
  224        * in this list, or -1 if this list does not contain the element.
  225        * More formally, returns the lowest index <tt>i</tt> such that
  226        * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
  227        * or -1 if there is no such index.
  228        */
  229       public int indexOf(Object o) {
  230           if (o == null) {
  231               for (int i = 0; i < size; i++)
  232                   if (elementData[i]==null)
  233                       return i;
  234           } else {
  235               for (int i = 0; i < size; i++)
  236                   if (o.equals(elementData[i]))
  237                       return i;
  238           }
  239           return -1;
  240       }
  241   
  242       /**
  243        * Returns the index of the last occurrence of the specified element
  244        * in this list, or -1 if this list does not contain the element.
  245        * More formally, returns the highest index <tt>i</tt> such that
  246        * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
  247        * or -1 if there is no such index.
  248        */
  249       public int lastIndexOf(Object o) {
  250           if (o == null) {
  251               for (int i = size-1; i >= 0; i--)
  252                   if (elementData[i]==null)
  253                       return i;
  254           } else {
  255               for (int i = size-1; i >= 0; i--)
  256                   if (o.equals(elementData[i]))
  257                       return i;
  258           }
  259           return -1;
  260       }
  261   
  262       /**
  263        * Returns a shallow copy of this <tt>ArrayList</tt> instance.  (The
  264        * elements themselves are not copied.)
  265        *
  266        * @return a clone of this <tt>ArrayList</tt> instance
  267        */
  268       public Object clone() {
  269           try {
  270               @SuppressWarnings("unchecked")
  271                   ArrayList<E> v = (ArrayList<E>) super.clone();
  272               v.elementData = Arrays.copyOf(elementData, size);
  273               v.modCount = 0;
  274               return v;
  275           } catch (CloneNotSupportedException e) {
  276               // this shouldn't happen, since we are Cloneable
  277               throw new InternalError();
  278           }
  279       }
  280   
  281       /**
  282        * Returns an array containing all of the elements in this list
  283        * in proper sequence (from first to last element).
  284        *
  285        * <p>The returned array will be "safe" in that no references to it are
  286        * maintained by this list.  (In other words, this method must allocate
  287        * a new array).  The caller is thus free to modify the returned array.
  288        *
  289        * <p>This method acts as bridge between array-based and collection-based
  290        * APIs.
  291        *
  292        * @return an array containing all of the elements in this list in
  293        *         proper sequence
  294        */
  295       public Object[] toArray() {
  296           return Arrays.copyOf(elementData, size);
  297       }
  298   
  299       /**
  300        * Returns an array containing all of the elements in this list in proper
  301        * sequence (from first to last element); the runtime type of the returned
  302        * array is that of the specified array.  If the list fits in the
  303        * specified array, it is returned therein.  Otherwise, a new array is
  304        * allocated with the runtime type of the specified array and the size of
  305        * this list.
  306        *
  307        * <p>If the list fits in the specified array with room to spare
  308        * (i.e., the array has more elements than the list), the element in
  309        * the array immediately following the end of the collection is set to
  310        * <tt>null</tt>.  (This is useful in determining the length of the
  311        * list <i>only</i> if the caller knows that the list does not contain
  312        * any null elements.)
  313        *
  314        * @param a the array into which the elements of the list are to
  315        *          be stored, if it is big enough; otherwise, a new array of the
  316        *          same runtime type is allocated for this purpose.
  317        * @return an array containing the elements of the list
  318        * @throws ArrayStoreException if the runtime type of the specified array
  319        *         is not a supertype of the runtime type of every element in
  320        *         this list
  321        * @throws NullPointerException if the specified array is null
  322        */
  323       @SuppressWarnings("unchecked")
  324       public <T> T[] toArray(T[] a) {
  325           if (a.length < size)
  326               // Make a new array of a's runtime type, but my contents:
  327               return (T[]) Arrays.copyOf(elementData, size, a.getClass());
  328           System.arraycopy(elementData, 0, a, 0, size);
  329           if (a.length > size)
  330               a[size] = null;
  331           return a;
  332       }
  333   
  334       // Positional Access Operations
  335   
  336       @SuppressWarnings("unchecked")
  337       E elementData(int index) {
  338           return (E) elementData[index];
  339       }
  340   
  341       /**
  342        * Returns the element at the specified position in this list.
  343        *
  344        * @param  index index of the element to return
  345        * @return the element at the specified position in this list
  346        * @throws IndexOutOfBoundsException {@inheritDoc}
  347        */
  348       public E get(int index) {
  349           rangeCheck(index);
  350   
  351           return elementData(index);
  352       }
  353   
  354       /**
  355        * Replaces the element at the specified position in this list with
  356        * the specified element.
  357        *
  358        * @param index index of the element to replace
  359        * @param element element to be stored at the specified position
  360        * @return the element previously at the specified position
  361        * @throws IndexOutOfBoundsException {@inheritDoc}
  362        */
  363       public E set(int index, E element) {
  364           rangeCheck(index);
  365   
  366           E oldValue = elementData(index);
  367           elementData[index] = element;
  368           return oldValue;
  369       }
  370   
  371       /**
  372        * Appends the specified element to the end of this list.
  373        *
  374        * @param e element to be appended to this list
  375        * @return <tt>true</tt> (as specified by {@link Collection#add})
  376        */
  377       public boolean add(E e) {
  378           ensureCapacity(size + 1);  // Increments modCount!!
  379           elementData[size++] = e;
  380           return true;
  381       }
  382   
  383       /**
  384        * Inserts the specified element at the specified position in this
  385        * list. Shifts the element currently at that position (if any) and
  386        * any subsequent elements to the right (adds one to their indices).
  387        *
  388        * @param index index at which the specified element is to be inserted
  389        * @param element element to be inserted
  390        * @throws IndexOutOfBoundsException {@inheritDoc}
  391        */
  392       public void add(int index, E element) {
  393           rangeCheckForAdd(index);
  394   
  395           ensureCapacity(size+1);  // Increments modCount!!
  396           System.arraycopy(elementData, index, elementData, index + 1,
  397                            size - index);
  398           elementData[index] = element;
  399           size++;
  400       }
  401   
  402       /**
  403        * Removes the element at the specified position in this list.
  404        * Shifts any subsequent elements to the left (subtracts one from their
  405        * indices).
  406        *
  407        * @param index the index of the element to be removed
  408        * @return the element that was removed from the list
  409        * @throws IndexOutOfBoundsException {@inheritDoc}
  410        */
  411       public E remove(int index) {
  412           rangeCheck(index);
  413   
  414           modCount++;
  415           E oldValue = elementData(index);
  416   
  417           int numMoved = size - index - 1;
  418           if (numMoved > 0)
  419               System.arraycopy(elementData, index+1, elementData, index,
  420                                numMoved);
  421           elementData[--size] = null; // Let gc do its work
  422   
  423           return oldValue;
  424       }
  425   
  426       /**
  427        * Removes the first occurrence of the specified element from this list,
  428        * if it is present.  If the list does not contain the element, it is
  429        * unchanged.  More formally, removes the element with the lowest index
  430        * <tt>i</tt> such that
  431        * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
  432        * (if such an element exists).  Returns <tt>true</tt> if this list
  433        * contained the specified element (or equivalently, if this list
  434        * changed as a result of the call).
  435        *
  436        * @param o element to be removed from this list, if present
  437        * @return <tt>true</tt> if this list contained the specified element
  438        */
  439       public boolean remove(Object o) {
  440           if (o == null) {
  441               for (int index = 0; index < size; index++)
  442                   if (elementData[index] == null) {
  443                       fastRemove(index);
  444                       return true;
  445                   }
  446           } else {
  447               for (int index = 0; index < size; index++)
  448                   if (o.equals(elementData[index])) {
  449                       fastRemove(index);
  450                       return true;
  451                   }
  452           }
  453           return false;
  454       }
  455   
  456       /*
  457        * Private remove method that skips bounds checking and does not
  458        * return the value removed.
  459        */
  460       private void fastRemove(int index) {
  461           modCount++;
  462           int numMoved = size - index - 1;
  463           if (numMoved > 0)
  464               System.arraycopy(elementData, index+1, elementData, index,
  465                                numMoved);
  466           elementData[--size] = null; // Let gc do its work
  467       }
  468   
  469       /**
  470        * Removes all of the elements from this list.  The list will
  471        * be empty after this call returns.
  472        */
  473       public void clear() {
  474           modCount++;
  475   
  476           // Let gc do its work
  477           for (int i = 0; i < size; i++)
  478               elementData[i] = null;
  479   
  480           size = 0;
  481       }
  482   
  483       /**
  484        * Appends all of the elements in the specified collection to the end of
  485        * this list, in the order that they are returned by the
  486        * specified collection's Iterator.  The behavior of this operation is
  487        * undefined if the specified collection is modified while the operation
  488        * is in progress.  (This implies that the behavior of this call is
  489        * undefined if the specified collection is this list, and this
  490        * list is nonempty.)
  491        *
  492        * @param c collection containing elements to be added to this list
  493        * @return <tt>true</tt> if this list changed as a result of the call
  494        * @throws NullPointerException if the specified collection is null
  495        */
  496       public boolean addAll(Collection<? extends E> c) {
  497           Object[] a = c.toArray();
  498           int numNew = a.length;
  499           ensureCapacity(size + numNew);  // Increments modCount
  500           System.arraycopy(a, 0, elementData, size, numNew);
  501           size += numNew;
  502           return numNew != 0;
  503       }
  504   
  505       /**
  506        * Inserts all of the elements in the specified collection into this
  507        * list, starting at the specified position.  Shifts the element
  508        * currently at that position (if any) and any subsequent elements to
  509        * the right (increases their indices).  The new elements will appear
  510        * in the list in the order that they are returned by the
  511        * specified collection's iterator.
  512        *
  513        * @param index index at which to insert the first element from the
  514        *              specified collection
  515        * @param c collection containing elements to be added to this list
  516        * @return <tt>true</tt> if this list changed as a result of the call
  517        * @throws IndexOutOfBoundsException {@inheritDoc}
  518        * @throws NullPointerException if the specified collection is null
  519        */
  520       public boolean addAll(int index, Collection<? extends E> c) {
  521           rangeCheckForAdd(index);
  522   
  523           Object[] a = c.toArray();
  524           int numNew = a.length;
  525           ensureCapacity(size + numNew);  // Increments modCount
  526   
  527           int numMoved = size - index;
  528           if (numMoved > 0)
  529               System.arraycopy(elementData, index, elementData, index + numNew,
  530                                numMoved);
  531   
  532           System.arraycopy(a, 0, elementData, index, numNew);
  533           size += numNew;
  534           return numNew != 0;
  535       }
  536   
  537       /**
  538        * Removes from this list all of the elements whose index is between
  539        * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
  540        * Shifts any succeeding elements to the left (reduces their index).
  541        * This call shortens the list by {@code (toIndex - fromIndex)} elements.
  542        * (If {@code toIndex==fromIndex}, this operation has no effect.)
  543        *
  544        * @throws IndexOutOfBoundsException if {@code fromIndex} or
  545        *         {@code toIndex} is out of range
  546        *         ({@code fromIndex < 0 ||
  547        *          fromIndex >= size() ||
  548        *          toIndex > size() ||
  549        *          toIndex < fromIndex})
  550        */
  551       protected void removeRange(int fromIndex, int toIndex) {
  552           modCount++;
  553           int numMoved = size - toIndex;
  554           System.arraycopy(elementData, toIndex, elementData, fromIndex,
  555                            numMoved);
  556   
  557           // Let gc do its work
  558           int newSize = size - (toIndex-fromIndex);
  559           while (size != newSize)
  560               elementData[--size] = null;
  561       }
  562   
  563       /**
  564        * Checks if the given index is in range.  If not, throws an appropriate
  565        * runtime exception.  This method does *not* check if the index is
  566        * negative: It is always used immediately prior to an array access,
  567        * which throws an ArrayIndexOutOfBoundsException if index is negative.
  568        */
  569       private void rangeCheck(int index) {
  570           if (index >= size)
  571               throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  572       }
  573   
  574       /**
  575        * A version of rangeCheck used by add and addAll.
  576        */
  577       private void rangeCheckForAdd(int index) {
  578           if (index > size || index < 0)
  579               throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  580       }
  581   
  582       /**
  583        * Constructs an IndexOutOfBoundsException detail message.
  584        * Of the many possible refactorings of the error handling code,
  585        * this "outlining" performs best with both server and client VMs.
  586        */
  587       private String outOfBoundsMsg(int index) {
  588           return "Index: "+index+", Size: "+size;
  589       }
  590   
  591       /**
  592        * Removes from this list all of its elements that are contained in the
  593        * specified collection.
  594        *
  595        * @param c collection containing elements to be removed from this list
  596        * @return {@code true} if this list changed as a result of the call
  597        * @throws ClassCastException if the class of an element of this list
  598        *         is incompatible with the specified collection (optional)
  599        * @throws NullPointerException if this list contains a null element and the
  600        *         specified collection does not permit null elements (optional),
  601        *         or if the specified collection is null
  602        * @see Collection#contains(Object)
  603        */
  604       public boolean removeAll(Collection<?> c) {
  605           return batchRemove(c, false);
  606       }
  607   
  608       /**
  609        * Retains only the elements in this list that are contained in the
  610        * specified collection.  In other words, removes from this list all
  611        * of its elements that are not contained in the specified collection.
  612        *
  613        * @param c collection containing elements to be retained in this list
  614        * @return {@code true} if this list changed as a result of the call
  615        * @throws ClassCastException if the class of an element of this list
  616        *         is incompatible with the specified collection (optional)
  617        * @throws NullPointerException if this list contains a null element and the
  618        *         specified collection does not permit null elements (optional),
  619        *         or if the specified collection is null
  620        * @see Collection#contains(Object)
  621        */
  622       public boolean retainAll(Collection<?> c) {
  623           return batchRemove(c, true);
  624       }
  625   
  626       private boolean batchRemove(Collection<?> c, boolean complement) {
  627           final Object[] elementData = this.elementData;
  628           int r = 0, w = 0;
  629           boolean modified = false;
  630           try {
  631               for (; r < size; r++)
  632                   if (c.contains(elementData[r]) == complement)
  633                       elementData[w++] = elementData[r];
  634           } finally {
  635               // Preserve behavioral compatibility with AbstractCollection,
  636               // even if c.contains() throws.
  637               if (r != size) {
  638                   System.arraycopy(elementData, r,
  639                                    elementData, w,
  640                                    size - r);
  641                   w += size - r;
  642               }
  643               if (w != size) {
  644                   for (int i = w; i < size; i++)
  645                       elementData[i] = null;
  646                   modCount += size - w;
  647                   size = w;
  648                   modified = true;
  649               }
  650           }
  651           return modified;
  652       }
  653   
  654       /**
  655        * Save the state of the <tt>ArrayList</tt> instance to a stream (that
  656        * is, serialize it).
  657        *
  658        * @serialData The length of the array backing the <tt>ArrayList</tt>
  659        *             instance is emitted (int), followed by all of its elements
  660        *             (each an <tt>Object</tt>) in the proper order.
  661        */
  662       private void writeObject(java.io.ObjectOutputStream s)
  663           throws java.io.IOException{
  664           // Write out element count, and any hidden stuff
  665           int expectedModCount = modCount;
  666           s.defaultWriteObject();
  667   
  668           // Write out array length
  669           s.writeInt(elementData.length);
  670   
  671           // Write out all elements in the proper order.
  672           for (int i=0; i<size; i++)
  673               s.writeObject(elementData[i]);
  674   
  675           if (modCount != expectedModCount) {
  676               throw new ConcurrentModificationException();
  677           }
  678   
  679       }
  680   
  681       /**
  682        * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
  683        * deserialize it).
  684        */
  685       private void readObject(java.io.ObjectInputStream s)
  686           throws java.io.IOException, ClassNotFoundException {
  687           // Read in size, and any hidden stuff
  688           s.defaultReadObject();
  689   
  690           // Read in array length and allocate array
  691           int arrayLength = s.readInt();
  692           Object[] a = elementData = new Object[arrayLength];
  693   
  694           // Read in all elements in the proper order.
  695           for (int i=0; i<size; i++)
  696               a[i] = s.readObject();
  697       }
  698   
  699       /**
  700        * Returns a list iterator over the elements in this list (in proper
  701        * sequence), starting at the specified position in the list.
  702        * The specified index indicates the first element that would be
  703        * returned by an initial call to {@link ListIterator#next next}.
  704        * An initial call to {@link ListIterator#previous previous} would
  705        * return the element with the specified index minus one.
  706        *
  707        * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
  708        *
  709        * @throws IndexOutOfBoundsException {@inheritDoc}
  710        */
  711       public ListIterator<E> listIterator(int index) {
  712           if (index < 0 || index > size)
  713               throw new IndexOutOfBoundsException("Index: "+index);
  714           return new ListItr(index);
  715       }
  716   
  717       /**
  718        * Returns a list iterator over the elements in this list (in proper
  719        * sequence).
  720        *
  721        * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
  722        *
  723        * @see #listIterator(int)
  724        */
  725       public ListIterator<E> listIterator() {
  726           return new ListItr(0);
  727       }
  728   
  729       /**
  730        * Returns an iterator over the elements in this list in proper sequence.
  731        *
  732        * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
  733        *
  734        * @return an iterator over the elements in this list in proper sequence
  735        */
  736       public Iterator<E> iterator() {
  737           return new Itr();
  738       }
  739   
  740       /**
  741        * An optimized version of AbstractList.Itr
  742        */
  743       private class Itr implements Iterator<E> {
  744           int cursor;       // index of next element to return
  745           int lastRet = -1; // index of last element returned; -1 if no such
  746           int expectedModCount = modCount;
  747   
  748           public boolean hasNext() {
  749               return cursor != size;
  750           }
  751   
  752           @SuppressWarnings("unchecked")
  753           public E next() {
  754               checkForComodification();
  755               int i = cursor;
  756               if (i >= size)
  757                   throw new NoSuchElementException();
  758               Object[] elementData = ArrayList.this.elementData;
  759               if (i >= elementData.length)
  760                   throw new ConcurrentModificationException();
  761               cursor = i + 1;
  762               return (E) elementData[lastRet = i];
  763           }
  764   
  765           public void remove() {
  766               if (lastRet < 0)
  767                   throw new IllegalStateException();
  768               checkForComodification();
  769   
  770               try {
  771                   ArrayList.this.remove(lastRet);
  772                   cursor = lastRet;
  773                   lastRet = -1;
  774                   expectedModCount = modCount;
  775               } catch (IndexOutOfBoundsException ex) {
  776                   throw new ConcurrentModificationException();
  777               }
  778           }
  779   
  780           final void checkForComodification() {
  781               if (modCount != expectedModCount)
  782                   throw new ConcurrentModificationException();
  783           }
  784       }
  785   
  786       /**
  787        * An optimized version of AbstractList.ListItr
  788        */
  789       private class ListItr extends Itr implements ListIterator<E> {
  790           ListItr(int index) {
  791               super();
  792               cursor = index;
  793           }
  794   
  795           public boolean hasPrevious() {
  796               return cursor != 0;
  797           }
  798   
  799           public int nextIndex() {
  800               return cursor;
  801           }
  802   
  803           public int previousIndex() {
  804               return cursor - 1;
  805           }
  806   
  807           @SuppressWarnings("unchecked")
  808           public E previous() {
  809               checkForComodification();
  810               int i = cursor - 1;
  811               if (i < 0)
  812                   throw new NoSuchElementException();
  813               Object[] elementData = ArrayList.this.elementData;
  814               if (i >= elementData.length)
  815                   throw new ConcurrentModificationException();
  816               cursor = i;
  817               return (E) elementData[lastRet = i];
  818           }
  819   
  820           public void set(E e) {
  821               if (lastRet < 0)
  822                   throw new IllegalStateException();
  823               checkForComodification();
  824   
  825               try {
  826                   ArrayList.this.set(lastRet, e);
  827               } catch (IndexOutOfBoundsException ex) {
  828                   throw new ConcurrentModificationException();
  829               }
  830           }
  831   
  832           public void add(E e) {
  833               checkForComodification();
  834   
  835               try {
  836                   int i = cursor;
  837                   ArrayList.this.add(i, e);
  838                   cursor = i + 1;
  839                   lastRet = -1;
  840                   expectedModCount = modCount;
  841               } catch (IndexOutOfBoundsException ex) {
  842                   throw new ConcurrentModificationException();
  843               }
  844           }
  845       }
  846   
  847       /**
  848        * Returns a view of the portion of this list between the specified
  849        * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.  (If
  850        * {@code fromIndex} and {@code toIndex} are equal, the returned list is
  851        * empty.)  The returned list is backed by this list, so non-structural
  852        * changes in the returned list are reflected in this list, and vice-versa.
  853        * The returned list supports all of the optional list operations.
  854        *
  855        * <p>This method eliminates the need for explicit range operations (of
  856        * the sort that commonly exist for arrays).  Any operation that expects
  857        * a list can be used as a range operation by passing a subList view
  858        * instead of a whole list.  For example, the following idiom
  859        * removes a range of elements from a list:
  860        * <pre>
  861        *      list.subList(from, to).clear();
  862        * </pre>
  863        * Similar idioms may be constructed for {@link #indexOf(Object)} and
  864        * {@link #lastIndexOf(Object)}, and all of the algorithms in the
  865        * {@link Collections} class can be applied to a subList.
  866        *
  867        * <p>The semantics of the list returned by this method become undefined if
  868        * the backing list (i.e., this list) is <i>structurally modified</i> in
  869        * any way other than via the returned list.  (Structural modifications are
  870        * those that change the size of this list, or otherwise perturb it in such
  871        * a fashion that iterations in progress may yield incorrect results.)
  872        *
  873        * @throws IndexOutOfBoundsException {@inheritDoc}
  874        * @throws IllegalArgumentException {@inheritDoc}
  875        */
  876       public List<E> subList(int fromIndex, int toIndex) {
  877           subListRangeCheck(fromIndex, toIndex, size);
  878           return new SubList(this, 0, fromIndex, toIndex);
  879       }
  880   
  881       static void subListRangeCheck(int fromIndex, int toIndex, int size) {
  882           if (fromIndex < 0)
  883               throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
  884           if (toIndex > size)
  885               throw new IndexOutOfBoundsException("toIndex = " + toIndex);
  886           if (fromIndex > toIndex)
  887               throw new IllegalArgumentException("fromIndex(" + fromIndex +
  888                                                  ") > toIndex(" + toIndex + ")");
  889       }
  890   
  891       private class SubList extends AbstractList<E> implements RandomAccess {
  892           private final AbstractList<E> parent;
  893           private final int parentOffset;
  894           private final int offset;
  895           int size;
  896   
  897           SubList(AbstractList<E> parent,
  898                   int offset, int fromIndex, int toIndex) {
  899               this.parent = parent;
  900               this.parentOffset = fromIndex;
  901               this.offset = offset + fromIndex;
  902               this.size = toIndex - fromIndex;
  903               this.modCount = ArrayList.this.modCount;
  904           }
  905   
  906           public E set(int index, E e) {
  907               rangeCheck(index);
  908               checkForComodification();
  909               E oldValue = ArrayList.this.elementData(offset + index);
  910               ArrayList.this.elementData[offset + index] = e;
  911               return oldValue;
  912           }
  913   
  914           public E get(int index) {
  915               rangeCheck(index);
  916               checkForComodification();
  917               return ArrayList.this.elementData(offset + index);
  918           }
  919   
  920           public int size() {
  921               checkForComodification();
  922               return this.size;
  923           }
  924   
  925           public void add(int index, E e) {
  926               rangeCheckForAdd(index);
  927               checkForComodification();
  928               parent.add(parentOffset + index, e);
  929               this.modCount = parent.modCount;
  930               this.size++;
  931           }
  932   
  933           public E remove(int index) {
  934               rangeCheck(index);
  935               checkForComodification();
  936               E result = parent.remove(parentOffset + index);
  937               this.modCount = parent.modCount;
  938               this.size--;
  939               return result;
  940           }
  941   
  942           protected void removeRange(int fromIndex, int toIndex) {
  943               checkForComodification();
  944               parent.removeRange(parentOffset + fromIndex,
  945                                  parentOffset + toIndex);
  946               this.modCount = parent.modCount;
  947               this.size -= toIndex - fromIndex;
  948           }
  949   
  950           public boolean addAll(Collection<? extends E> c) {
  951               return addAll(this.size, c);
  952           }
  953   
  954           public boolean addAll(int index, Collection<? extends E> c) {
  955               rangeCheckForAdd(index);
  956               int cSize = c.size();
  957               if (cSize==0)
  958                   return false;
  959   
  960               checkForComodification();
  961               parent.addAll(parentOffset + index, c);
  962               this.modCount = parent.modCount;
  963               this.size += cSize;
  964               return true;
  965           }
  966   
  967           public Iterator<E> iterator() {
  968               return listIterator();
  969           }
  970   
  971           public ListIterator<E> listIterator(final int index) {
  972               checkForComodification();
  973               rangeCheckForAdd(index);
  974               final int offset = this.offset;
  975   
  976               return new ListIterator<E>() {
  977                   int cursor = index;
  978                   int lastRet = -1;
  979                   int expectedModCount = ArrayList.this.modCount;
  980   
  981                   public boolean hasNext() {
  982                       return cursor != SubList.this.size;
  983                   }
  984   
  985                   @SuppressWarnings("unchecked")
  986                   public E next() {
  987                       checkForComodification();
  988                       int i = cursor;
  989                       if (i >= SubList.this.size)
  990                           throw new NoSuchElementException();
  991                       Object[] elementData = ArrayList.this.elementData;
  992                       if (offset + i >= elementData.length)
  993                           throw new ConcurrentModificationException();
  994                       cursor = i + 1;
  995                       return (E) elementData[offset + (lastRet = i)];
  996                   }
  997   
  998                   public boolean hasPrevious() {
  999                       return cursor != 0;
 1000                   }
 1001   
 1002                   @SuppressWarnings("unchecked")
 1003                   public E previous() {
 1004                       checkForComodification();
 1005                       int i = cursor - 1;
 1006                       if (i < 0)
 1007                           throw new NoSuchElementException();
 1008                       Object[] elementData = ArrayList.this.elementData;
 1009                       if (offset + i >= elementData.length)
 1010                           throw new ConcurrentModificationException();
 1011                       cursor = i;
 1012                       return (E) elementData[offset + (lastRet = i)];
 1013                   }
 1014   
 1015                   public int nextIndex() {
 1016                       return cursor;
 1017                   }
 1018   
 1019                   public int previousIndex() {
 1020                       return cursor - 1;
 1021                   }
 1022   
 1023                   public void remove() {
 1024                       if (lastRet < 0)
 1025                           throw new IllegalStateException();
 1026                       checkForComodification();
 1027   
 1028                       try {
 1029                           SubList.this.remove(lastRet);
 1030                           cursor = lastRet;
 1031                           lastRet = -1;
 1032                           expectedModCount = ArrayList.this.modCount;
 1033                       } catch (IndexOutOfBoundsException ex) {
 1034                           throw new ConcurrentModificationException();
 1035                       }
 1036                   }
 1037   
 1038                   public void set(E e) {
 1039                       if (lastRet < 0)
 1040                           throw new IllegalStateException();
 1041                       checkForComodification();
 1042   
 1043                       try {
 1044                           ArrayList.this.set(offset + lastRet, e);
 1045                       } catch (IndexOutOfBoundsException ex) {
 1046                           throw new ConcurrentModificationException();
 1047                       }
 1048                   }
 1049   
 1050                   public void add(E e) {
 1051                       checkForComodification();
 1052   
 1053                       try {
 1054                           int i = cursor;
 1055                           SubList.this.add(i, e);
 1056                           cursor = i + 1;
 1057                           lastRet = -1;
 1058                           expectedModCount = ArrayList.this.modCount;
 1059                       } catch (IndexOutOfBoundsException ex) {
 1060                           throw new ConcurrentModificationException();
 1061                       }
 1062                   }
 1063   
 1064                   final void checkForComodification() {
 1065                       if (expectedModCount != ArrayList.this.modCount)
 1066                           throw new ConcurrentModificationException();
 1067                   }
 1068               };
 1069           }
 1070   
 1071           public List<E> subList(int fromIndex, int toIndex) {
 1072               subListRangeCheck(fromIndex, toIndex, size);
 1073               return new SubList(this, offset, fromIndex, toIndex);
 1074           }
 1075   
 1076           private void rangeCheck(int index) {
 1077               if (index < 0 || index >= this.size)
 1078                   throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
 1079           }
 1080   
 1081           private void rangeCheckForAdd(int index) {
 1082               if (index < 0 || index > this.size)
 1083                   throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
 1084           }
 1085   
 1086           private String outOfBoundsMsg(int index) {
 1087               return "Index: "+index+", Size: "+this.size;
 1088           }
 1089   
 1090           private void checkForComodification() {
 1091               if (ArrayList.this.modCount != this.modCount)
 1092                   throw new ConcurrentModificationException();
 1093           }
 1094       }
 1095   }

Save This Page
Home » openjdk-7 » java » util » [javadoc | source]