ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/ArrayList.java
Revision: 1.16
Committed: Tue Feb 7 20:54:24 2006 UTC (18 years, 3 months ago) by jsr166
Branch: MAIN
Changes since 1.15: +0 -1 lines
Log Message:
6378729: Remove workaround for 6280605

File Contents

# User Rev Content
1 dl 1.1 /*
2     * %W% %E%
3     *
4 jsr166 1.14 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5 dl 1.1 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6     */
7    
8     package java.util;
9    
10     /**
11     * Resizable-array implementation of the <tt>List</tt> interface. Implements
12     * all optional list operations, and permits all elements, including
13     * <tt>null</tt>. In addition to implementing the <tt>List</tt> interface,
14     * this class provides methods to manipulate the size of the array that is
15     * used internally to store the list. (This class is roughly equivalent to
16     * <tt>Vector</tt>, except that it is unsynchronized.)<p>
17     *
18     * The <tt>size</tt>, <tt>isEmpty</tt>, <tt>get</tt>, <tt>set</tt>,
19     * <tt>iterator</tt>, and <tt>listIterator</tt> operations run in constant
20     * time. The <tt>add</tt> operation runs in <i>amortized constant time</i>,
21     * that is, adding n elements requires O(n) time. All of the other operations
22     * run in linear time (roughly speaking). The constant factor is low compared
23     * to that for the <tt>LinkedList</tt> implementation.<p>
24     *
25     * Each <tt>ArrayList</tt> instance has a <i>capacity</i>. The capacity is
26     * the size of the array used to store the elements in the list. It is always
27     * at least as large as the list size. As elements are added to an ArrayList,
28     * its capacity grows automatically. The details of the growth policy are not
29     * specified beyond the fact that adding an element has constant amortized
30     * time cost.<p>
31     *
32     * An application can increase the capacity of an <tt>ArrayList</tt> instance
33     * before adding a large number of elements using the <tt>ensureCapacity</tt>
34     * operation. This may reduce the amount of incremental reallocation.
35     *
36     * <p><strong>Note that this implementation is not synchronized.</strong>
37     * If multiple threads access an <tt>ArrayList</tt> instance concurrently,
38     * and at least one of the threads modifies the list structurally, it
39     * <i>must</i> be synchronized externally. (A structural modification is
40     * any operation that adds or deletes one or more elements, or explicitly
41     * resizes the backing array; merely setting the value of an element is not
42     * a structural modification.) This is typically accomplished by
43     * synchronizing on some object that naturally encapsulates the list.
44     *
45     * If no such object exists, the list should be "wrapped" using the
46     * {@link Collections#synchronizedList Collections.synchronizedList}
47     * method. This is best done at creation time, to prevent accidental
48     * unsynchronized access to the list:<pre>
49     * List list = Collections.synchronizedList(new ArrayList(...));</pre>
50     *
51     * <p>The iterators returned by this class's <tt>iterator</tt> and
52     * <tt>listIterator</tt> methods are <i>fail-fast</i>: if the list is
53     * structurally modified at any time after the iterator is created, in any way
54     * except through the iterator's own <tt>remove</tt> or <tt>add</tt> methods,
55     * the iterator will throw a {@link ConcurrentModificationException}. Thus, in
56     * the face of concurrent modification, the iterator fails quickly and cleanly,
57     * rather than risking arbitrary, non-deterministic behavior at an undetermined
58     * time in the future.<p>
59     *
60     * Note that the fail-fast behavior of an iterator cannot be guaranteed
61     * as it is, generally speaking, impossible to make any hard guarantees in the
62     * presence of unsynchronized concurrent modification. Fail-fast iterators
63     * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
64     * Therefore, it would be wrong to write a program that depended on this
65     * exception for its correctness: <i>the fail-fast behavior of iterators
66     * should be used only to detect bugs.</i><p>
67     *
68     * This class is a member of the
69     * <a href="{@docRoot}/../guide/collections/index.html">
70     * Java Collections Framework</a>.
71     *
72     * @author Josh Bloch
73     * @author Neal Gafter
74     * @version %I%, %G%
75     * @see Collection
76     * @see List
77     * @see LinkedList
78     * @see Vector
79     * @since 1.2
80     */
81    
82     public class ArrayList<E> extends AbstractList<E>
83     implements List<E>, RandomAccess, Cloneable, java.io.Serializable
84     {
85     private static final long serialVersionUID = 8683452581122892189L;
86    
87     /**
88     * The array buffer into which the elements of the ArrayList are stored.
89     * The capacity of the ArrayList is the length of this array buffer.
90     */
91     private transient Object[] elementData;
92    
93     /**
94     * The size of the ArrayList (the number of elements it contains).
95     *
96     * @serial
97     */
98     private int size;
99    
100     /**
101     * Constructs an empty list with the specified initial capacity.
102     *
103 jsr166 1.5 * @param initialCapacity the initial capacity of the list
104     * @throws IllegalArgumentException if the specified initial capacity
105     * is negative
106 dl 1.1 */
107     public ArrayList(int initialCapacity) {
108     super();
109     if (initialCapacity < 0)
110     throw new IllegalArgumentException("Illegal Capacity: "+
111     initialCapacity);
112     this.elementData = new Object[initialCapacity];
113     }
114    
115     /**
116     * Constructs an empty list with an initial capacity of ten.
117     */
118     public ArrayList() {
119     this(10);
120     }
121    
122     /**
123     * Constructs a list containing the elements of the specified
124     * collection, in the order they are returned by the collection's
125 dl 1.2 * iterator. The <tt>ArrayList</tt> instance has an initial capacity of
126     * 110% the size of the specified collection.
127 dl 1.1 *
128     * @param c the collection whose elements are to be placed into this list
129     * @throws NullPointerException if the specified collection is null
130     */
131     public ArrayList(Collection<? extends E> c) {
132 dl 1.2 int size = c.size();
133     // 10% for growth
134     int cap = ((size/10)+1)*11;
135     if (cap > 0) {
136     Object[] a = new Object[cap];
137     a[size] = a[size+1] = UNALLOCATED;
138     Object[] b = c.toArray(a);
139     if (b[size] == null && b[size+1] == UNALLOCATED) {
140     b[size+1] = null;
141     elementData = b;
142     this.size = size;
143     return;
144     }
145     }
146     initFromConcurrentlyMutating(c);
147     }
148 jsr166 1.4
149 dl 1.2 private void initFromConcurrentlyMutating(Collection<? extends E> c) {
150     elementData = c.toArray();
151     size = elementData.length;
152     // c.toArray might (incorrectly) not return Object[] (see 6260652)
153     if (elementData.getClass() != Object[].class)
154     elementData = Arrays.copyOf(elementData, size, Object[].class);
155     }
156 jsr166 1.4
157 dl 1.2 private final static Object UNALLOCATED = new Object();
158 jsr166 1.4
159 dl 1.1 /**
160     * Trims the capacity of this <tt>ArrayList</tt> instance to be the
161     * list's current size. An application can use this operation to minimize
162     * the storage of an <tt>ArrayList</tt> instance.
163     */
164     public void trimToSize() {
165     modCount++;
166     int oldCapacity = elementData.length;
167     if (size < oldCapacity) {
168     elementData = Arrays.copyOf(elementData, size);
169     }
170     }
171    
172     /**
173     * Increases the capacity of this <tt>ArrayList</tt> instance, if
174     * necessary, to ensure that it can hold at least the number of elements
175     * specified by the minimum capacity argument.
176     *
177 jsr166 1.5 * @param minCapacity the desired minimum capacity
178 dl 1.1 */
179     public void ensureCapacity(int minCapacity) {
180     modCount++;
181     if (minCapacity > elementData.length)
182     growArray(minCapacity);
183     }
184    
185     /**
186 jsr166 1.5 * Increases the capacity of the array.
187     *
188     * @param minCapacity the desired minimum capacity
189 dl 1.1 */
190     private void growArray(int minCapacity) {
191 dl 1.13 if (minCapacity < 0) // overflow
192 jsr166 1.15 throw new OutOfMemoryError();
193 dl 1.1 int oldCapacity = elementData.length;
194     // Double size if small; else grow by 50%
195 jsr166 1.4 int newCapacity = ((oldCapacity < 64)?
196 dl 1.9 ((oldCapacity + 1) * 2):
197 dl 1.13 ((oldCapacity / 2) * 3));
198     if (newCapacity < 0) // overflow
199     newCapacity = Integer.MAX_VALUE;
200 dl 1.1 if (newCapacity < minCapacity)
201     newCapacity = minCapacity;
202     elementData = Arrays.copyOf(elementData, newCapacity);
203     }
204    
205     /**
206     * Returns the number of elements in this list.
207     *
208     * @return the number of elements in this list
209     */
210     public int size() {
211     return size;
212     }
213    
214     /**
215     * Returns <tt>true</tt> if this list contains no elements.
216     *
217     * @return <tt>true</tt> if this list contains no elements
218     */
219     public boolean isEmpty() {
220     return size == 0;
221     }
222    
223     /**
224     * Returns <tt>true</tt> if this list contains the specified element.
225     * More formally, returns <tt>true</tt> if and only if this list contains
226     * at least one element <tt>e</tt> such that
227     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
228     *
229     * @param o element whose presence in this list is to be tested
230     * @return <tt>true</tt> if this list contains the specified element
231     */
232     public boolean contains(Object o) {
233     return indexOf(o) >= 0;
234     }
235    
236     /**
237     * Returns the index of the first occurrence of the specified element
238     * in this list, or -1 if this list does not contain the element.
239     * More formally, returns the lowest index <tt>i</tt> such that
240     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
241     * or -1 if there is no such index.
242     */
243     public int indexOf(Object o) {
244     if (o == null) {
245     for (int i = 0; i < size; i++)
246     if (elementData[i]==null)
247     return i;
248     } else {
249     for (int i = 0; i < size; i++)
250     if (o.equals(elementData[i]))
251     return i;
252     }
253     return -1;
254     }
255    
256     /**
257     * Returns the index of the last occurrence of the specified element
258     * in this list, or -1 if this list does not contain the element.
259     * More formally, returns the highest index <tt>i</tt> such that
260     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
261     * or -1 if there is no such index.
262     */
263     public int lastIndexOf(Object o) {
264     if (o == null) {
265     for (int i = size-1; i >= 0; i--)
266     if (elementData[i]==null)
267     return i;
268     } else {
269     for (int i = size-1; i >= 0; i--)
270     if (o.equals(elementData[i]))
271     return i;
272     }
273     return -1;
274     }
275    
276     /**
277     * Returns a shallow copy of this <tt>ArrayList</tt> instance. (The
278     * elements themselves are not copied.)
279     *
280     * @return a clone of this <tt>ArrayList</tt> instance
281     */
282     public Object clone() {
283     try {
284     ArrayList<E> v = (ArrayList<E>) super.clone();
285     v.elementData = Arrays.copyOf(elementData, size);
286     v.modCount = 0;
287     return v;
288     } catch (CloneNotSupportedException e) {
289     // this shouldn't happen, since we are Cloneable
290     throw new InternalError();
291     }
292     }
293    
294     /**
295     * Returns an array containing all of the elements in this list
296     * in proper sequence (from first to last element).
297     *
298     * <p>The returned array will be "safe" in that no references to it are
299     * maintained by this list. (In other words, this method must allocate
300     * a new array). The caller is thus free to modify the returned array.
301     *
302     * <p>This method acts as bridge between array-based and collection-based
303     * APIs.
304     *
305     * @return an array containing all of the elements in this list in
306     * proper sequence
307     */
308     public Object[] toArray() {
309     return Arrays.copyOf(elementData, size);
310     }
311    
312     /**
313     * Returns an array containing all of the elements in this list in proper
314     * sequence (from first to last element); the runtime type of the returned
315     * array is that of the specified array. If the list fits in the
316     * specified array, it is returned therein. Otherwise, a new array is
317     * allocated with the runtime type of the specified array and the size of
318     * this list.
319     *
320     * <p>If the list fits in the specified array with room to spare
321     * (i.e., the array has more elements than the list), the element in
322     * the array immediately following the end of the collection is set to
323     * <tt>null</tt>. (This is useful in determining the length of the
324     * list <i>only</i> if the caller knows that the list does not contain
325     * any null elements.)
326     *
327     * @param a the array into which the elements of the list are to
328     * be stored, if it is big enough; otherwise, a new array of the
329     * same runtime type is allocated for this purpose.
330     * @return an array containing the elements of the list
331     * @throws ArrayStoreException if the runtime type of the specified array
332     * is not a supertype of the runtime type of every element in
333     * this list
334     * @throws NullPointerException if the specified array is null
335     */
336     public <T> T[] toArray(T[] a) {
337     if (a.length < size)
338     // Make a new array of a's runtime type, but my contents:
339     return (T[]) Arrays.copyOf(elementData, size, a.getClass());
340     System.arraycopy(elementData, 0, a, 0, size);
341     if (a.length > size)
342     a[size] = null;
343     return a;
344     }
345    
346     // Positional Access Operations
347    
348 jsr166 1.4 /**
349 dl 1.9 * Returns error message string for IndexOutOfBoundsExceptions
350 dl 1.1 */
351 dl 1.9 private String ioobe(int index) {
352     return "Index: " + index + ", Size: " + size;
353 dl 1.1 }
354    
355     /**
356     * Returns the element at the specified position in this list.
357     *
358     * @param index index of the element to return
359     * @return the element at the specified position in this list
360     * @throws IndexOutOfBoundsException {@inheritDoc}
361     */
362     public E get(int index) {
363     if (index >= size)
364 dl 1.9 throw new IndexOutOfBoundsException(ioobe(index));
365 dl 1.1 return (E)elementData[index];
366     }
367    
368     /**
369     * Replaces the element at the specified position in this list with
370     * the specified element.
371     *
372     * @param index index of the element to replace
373     * @param element element to be stored at the specified position
374     * @return the element previously at the specified position
375     * @throws IndexOutOfBoundsException {@inheritDoc}
376     */
377     public E set(int index, E element) {
378     if (index >= size)
379 dl 1.9 throw new IndexOutOfBoundsException(ioobe(index));
380 dl 1.1
381     E oldValue = (E) elementData[index];
382     elementData[index] = element;
383     return oldValue;
384     }
385    
386     /**
387     * Appends the specified element to the end of this list.
388     *
389     * @param e element to be appended to this list
390     * @return <tt>true</tt> (as specified by {@link Collection#add})
391     */
392     public boolean add(E e) {
393 jsr166 1.8 modCount++;
394 dl 1.7 int s = size;
395 dl 1.1 if (s >= elementData.length)
396     growArray(s + 1);
397     elementData[s] = e;
398 dl 1.7 size = s + 1;
399 dl 1.1 return true;
400     }
401    
402     /**
403     * Inserts the specified element at the specified position in this
404     * list. Shifts the element currently at that position (if any) and
405     * any subsequent elements to the right (adds one to their indices).
406     *
407     * @param index index at which the specified element is to be inserted
408     * @param element element to be inserted
409     * @throws IndexOutOfBoundsException {@inheritDoc}
410     */
411     public void add(int index, E element) {
412     int s = size;
413     if (index > s || index < 0)
414 dl 1.9 throw new IndexOutOfBoundsException(ioobe(index));
415 jsr166 1.8 modCount++;
416 dl 1.1 if (s >= elementData.length)
417     growArray(s + 1);
418 jsr166 1.10 System.arraycopy(elementData, index,
419 dl 1.7 elementData, index + 1, s - index);
420 dl 1.1 elementData[index] = element;
421 dl 1.7 size = s + 1;
422 dl 1.1 }
423    
424     /**
425     * Removes the element at the specified position in this list.
426     * Shifts any subsequent elements to the left (subtracts one from their
427     * indices).
428     *
429     * @param index the index of the element to be removed
430     * @return the element that was removed from the list
431     * @throws IndexOutOfBoundsException {@inheritDoc}
432     */
433     public E remove(int index) {
434     int s = size - 1;
435 jsr166 1.8 if (index > s)
436 dl 1.9 throw new IndexOutOfBoundsException(ioobe(index));
437 dl 1.1 modCount++;
438 dl 1.7 E oldValue = (E)elementData[index];
439 dl 1.1 int numMoved = s - index;
440     if (numMoved > 0)
441 jsr166 1.10 System.arraycopy(elementData, index + 1,
442 dl 1.7 elementData, index, numMoved);
443 jsr166 1.8 elementData[s] = null;
444 dl 1.7 size = s;
445     return oldValue;
446 dl 1.1 }
447    
448     /**
449     * Removes the first occurrence of the specified element from this list,
450     * if it is present. If the list does not contain the element, it is
451     * unchanged. More formally, removes the element with the lowest index
452     * <tt>i</tt> such that
453     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
454     * (if such an element exists). Returns <tt>true</tt> if this list
455     * contained the specified element (or equivalently, if this list
456     * changed as a result of the call).
457     *
458     * @param o element to be removed from this list, if present
459     * @return <tt>true</tt> if this list contained the specified element
460     */
461     public boolean remove(Object o) {
462     if (o == null) {
463     for (int index = 0; index < size; index++)
464     if (elementData[index] == null) {
465     fastRemove(index);
466     return true;
467     }
468     } else {
469     for (int index = 0; index < size; index++)
470     if (o.equals(elementData[index])) {
471     fastRemove(index);
472     return true;
473     }
474     }
475     return false;
476     }
477    
478     /*
479     * Private remove method that skips bounds checking and does not
480     * return the value removed.
481     */
482     private void fastRemove(int index) {
483     modCount++;
484     int numMoved = size - index - 1;
485     if (numMoved > 0)
486     System.arraycopy(elementData, index+1, elementData, index,
487     numMoved);
488     elementData[--size] = null; // Let gc do its work
489     }
490    
491     /**
492     * Removes all of the elements from this list. The list will
493     * be empty after this call returns.
494     */
495     public void clear() {
496     modCount++;
497    
498     // Let gc do its work
499     for (int i = 0; i < size; i++)
500     elementData[i] = null;
501    
502     size = 0;
503     }
504    
505     /**
506     * Appends all of the elements in the specified collection to the end of
507     * this list, in the order that they are returned by the
508     * specified collection's Iterator. The behavior of this operation is
509     * undefined if the specified collection is modified while the operation
510     * is in progress. (This implies that the behavior of this call is
511     * undefined if the specified collection is this list, and this
512     * list is nonempty.)
513     *
514     * @param c collection containing elements to be added to this list
515     * @return <tt>true</tt> if this list changed as a result of the call
516     * @throws NullPointerException if the specified collection is null
517     */
518     public boolean addAll(Collection<? extends E> c) {
519     Object[] a = c.toArray();
520     int numNew = a.length;
521     ensureCapacity(size + numNew); // Increments modCount
522     System.arraycopy(a, 0, elementData, size, numNew);
523     size += numNew;
524     return numNew != 0;
525     }
526    
527     /**
528     * Inserts all of the elements in the specified collection into this
529     * list, starting at the specified position. Shifts the element
530     * currently at that position (if any) and any subsequent elements to
531     * the right (increases their indices). The new elements will appear
532     * in the list in the order that they are returned by the
533     * specified collection's iterator.
534     *
535     * @param index index at which to insert the first element from the
536     * specified collection
537     * @param c collection containing elements to be added to this list
538     * @return <tt>true</tt> if this list changed as a result of the call
539     * @throws IndexOutOfBoundsException {@inheritDoc}
540     * @throws NullPointerException if the specified collection is null
541     */
542     public boolean addAll(int index, Collection<? extends E> c) {
543     if (index > size || index < 0)
544 dl 1.9 throw new IndexOutOfBoundsException(ioobe(index));
545 dl 1.1
546     Object[] a = c.toArray();
547     int numNew = a.length;
548     ensureCapacity(size + numNew); // Increments modCount
549    
550     int numMoved = size - index;
551     if (numMoved > 0)
552     System.arraycopy(elementData, index, elementData, index + numNew,
553     numMoved);
554    
555     System.arraycopy(a, 0, elementData, index, numNew);
556     size += numNew;
557     return numNew != 0;
558     }
559    
560     /**
561     * Removes from this list all of the elements whose index is between
562     * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
563     * Shifts any succeeding elements to the left (reduces their index).
564     * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
565     * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
566     *
567     * @param fromIndex index of first element to be removed
568     * @param toIndex index after last element to be removed
569     * @throws IndexOutOfBoundsException if fromIndex or toIndex out of
570     * range (fromIndex &lt; 0 || fromIndex &gt;= size() || toIndex
571     * &gt; size() || toIndex &lt; fromIndex)
572     */
573     protected void removeRange(int fromIndex, int toIndex) {
574     modCount++;
575     int numMoved = size - toIndex;
576     System.arraycopy(elementData, toIndex, elementData, fromIndex,
577     numMoved);
578    
579     // Let gc do its work
580     int newSize = size - (toIndex-fromIndex);
581     while (size != newSize)
582     elementData[--size] = null;
583     }
584    
585     /**
586     * Save the state of the <tt>ArrayList</tt> instance to a stream (that
587     * is, serialize it).
588     *
589     * @serialData The length of the array backing the <tt>ArrayList</tt>
590     * instance is emitted (int), followed by all of its elements
591     * (each an <tt>Object</tt>) in the proper order.
592     */
593     private void writeObject(java.io.ObjectOutputStream s)
594     throws java.io.IOException{
595     // Write out element count, and any hidden stuff
596     int expectedModCount = modCount;
597     s.defaultWriteObject();
598    
599     // Write out array length
600     s.writeInt(elementData.length);
601    
602     // Write out all elements in the proper order.
603     for (int i=0; i<size; i++)
604     s.writeObject(elementData[i]);
605    
606 jsr166 1.12 if (expectedModCount != modCount) {
607 dl 1.1 throw new ConcurrentModificationException();
608     }
609    
610     }
611    
612     /**
613     * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
614     * deserialize it).
615     */
616     private void readObject(java.io.ObjectInputStream s)
617     throws java.io.IOException, ClassNotFoundException {
618     // Read in size, and any hidden stuff
619     s.defaultReadObject();
620    
621     // Read in array length and allocate array
622     int arrayLength = s.readInt();
623     Object[] a = elementData = new Object[arrayLength];
624    
625     // Read in all elements in the proper order.
626     for (int i=0; i<size; i++)
627     a[i] = s.readObject();
628     }
629    
630    
631     /**
632     * Returns a list-iterator of the elements in this list (in proper
633     * sequence), starting at the specified position in the list.
634     * Obeys the general contract of <tt>List.listIterator(int)</tt>.<p>
635     *
636     * The list-iterator is <i>fail-fast</i>: if the list is structurally
637     * modified at any time after the Iterator is created, in any way except
638     * through the list-iterator's own <tt>remove</tt> or <tt>add</tt>
639     * methods, the list-iterator will throw a
640     * <tt>ConcurrentModificationException</tt>. Thus, in the face of
641     * concurrent modification, the iterator fails quickly and cleanly, rather
642     * than risking arbitrary, non-deterministic behavior at an undetermined
643     * time in the future.
644     *
645     * @param index index of the first element to be returned from the
646     * list-iterator (by a call to <tt>next</tt>)
647     * @return a ListIterator of the elements in this list (in proper
648     * sequence), starting at the specified position in the list
649     * @throws IndexOutOfBoundsException {@inheritDoc}
650     * @see List#listIterator(int)
651     */
652     public ListIterator<E> listIterator(int index) {
653     if (index < 0 || index > size)
654 dl 1.9 throw new IndexOutOfBoundsException(ioobe(index));
655 dl 1.1 return new ArrayListIterator(index);
656     }
657 jsr166 1.4
658 dl 1.1 /**
659 dl 1.9 * {@inheritDoc}
660     */
661     public ListIterator<E> listIterator() {
662     return new ArrayListIterator(0);
663     }
664    
665     /**
666 dl 1.1 * Returns an iterator over the elements in this list in proper sequence.
667     *
668     * @return an iterator over the elements in this list in proper sequence
669     */
670     public Iterator<E> iterator() {
671     return new ArrayListIterator(0);
672     }
673    
674     /**
675 dl 1.9 * A streamlined version of AbstractList.ListItr
676 dl 1.1 */
677     final class ArrayListIterator implements ListIterator<E> {
678     int cursor; // index of next element to return;
679     int lastRet; // index of last element, or -1 if no such
680     int expectedModCount; // to check for CME
681    
682     ArrayListIterator(int index) {
683     cursor = index;
684     lastRet = -1;
685     expectedModCount = modCount;
686     }
687    
688     public boolean hasNext() {
689 dl 1.13 return cursor != size;
690 dl 1.1 }
691    
692     public boolean hasPrevious() {
693 dl 1.13 return cursor != 0;
694 dl 1.1 }
695    
696     public int nextIndex() {
697     return cursor;
698     }
699    
700     public int previousIndex() {
701     return cursor - 1;
702     }
703    
704     public E next() {
705 dl 1.9 try {
706 dl 1.1 int i = cursor;
707 dl 1.9 E next = get(i);
708     lastRet = i;
709     cursor = i + 1;
710     return next;
711     } catch (IndexOutOfBoundsException ex) {
712     throw new NoSuchElementException();
713     } finally {
714     if (expectedModCount != modCount)
715     throw new ConcurrentModificationException();
716 dl 1.1 }
717     }
718 jsr166 1.11
719 dl 1.1 public E previous() {
720 dl 1.9 try {
721 dl 1.1 int i = cursor - 1;
722 jsr166 1.11 E prev = get(i);
723 dl 1.9 lastRet = i;
724     cursor = i;
725 jsr166 1.11 return prev;
726 dl 1.9 } catch (IndexOutOfBoundsException ex) {
727     throw new NoSuchElementException();
728     } finally {
729 jsr166 1.12 if (expectedModCount != modCount)
730 dl 1.9 throw new ConcurrentModificationException();
731 dl 1.1 }
732     }
733    
734     public void remove() {
735     if (lastRet < 0)
736     throw new IllegalStateException();
737 jsr166 1.12 if (expectedModCount != modCount)
738 dl 1.1 throw new ConcurrentModificationException();
739     ArrayList.this.remove(lastRet);
740     if (lastRet < cursor)
741     cursor--;
742     lastRet = -1;
743     expectedModCount = modCount;
744     }
745    
746     public void set(E e) {
747     if (lastRet < 0)
748     throw new IllegalStateException();
749 jsr166 1.12 if (expectedModCount != modCount)
750 dl 1.1 throw new ConcurrentModificationException();
751     ArrayList.this.set(lastRet, e);
752     expectedModCount = modCount;
753     }
754    
755     public void add(E e) {
756 jsr166 1.12 if (expectedModCount != modCount)
757 dl 1.1 throw new ConcurrentModificationException();
758 dl 1.13 try {
759     ArrayList.this.add(cursor++, e);
760     lastRet = -1;
761     expectedModCount = modCount;
762     } catch (IndexOutOfBoundsException ex) {
763     throw new ConcurrentModificationException();
764     }
765 dl 1.1 }
766     }
767     }