ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/ArrayList.java
Revision: 1.19
Committed: Wed Apr 19 15:07:14 2006 UTC (18 years ago) by dl
Branch: MAIN
Changes since 1.18: +36 -165 lines
Log Message:
Updated Navigable interfaces ind implementations

File Contents

# User Rev Content
1 dl 1.1 /*
2 dl 1.19 * @(#)ArrayList.java 1.56 06/03/14
3 dl 1.1 *
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 dl 1.19 * @version 1.56, 03/14/06
75 dl 1.1 * @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 jsr166 1.17 * iterator.
126 dl 1.1 *
127     * @param c the collection whose elements are to be placed into this list
128     * @throws NullPointerException if the specified collection is null
129     */
130     public ArrayList(Collection<? extends E> c) {
131 dl 1.2 elementData = c.toArray();
132     size = elementData.length;
133     // c.toArray might (incorrectly) not return Object[] (see 6260652)
134     if (elementData.getClass() != Object[].class)
135     elementData = Arrays.copyOf(elementData, size, Object[].class);
136     }
137 jsr166 1.4
138 dl 1.19 private void initFromConcurrentlyMutating(Collection<? extends E> c) {
139     elementData = c.toArray();
140     size = elementData.length;
141     // c.toArray might (incorrectly) not return Object[] (see 6260652)
142     if (elementData.getClass() != Object[].class)
143     elementData = Arrays.copyOf(elementData, size, Object[].class);
144     }
145    
146     private final static Object UNALLOCATED = new Object();
147    
148 dl 1.1 /**
149     * Trims the capacity of this <tt>ArrayList</tt> instance to be the
150     * list's current size. An application can use this operation to minimize
151     * the storage of an <tt>ArrayList</tt> instance.
152     */
153     public void trimToSize() {
154     modCount++;
155     int oldCapacity = elementData.length;
156     if (size < oldCapacity) {
157     elementData = Arrays.copyOf(elementData, size);
158     }
159     }
160    
161     /**
162     * Increases the capacity of this <tt>ArrayList</tt> instance, if
163     * necessary, to ensure that it can hold at least the number of elements
164     * specified by the minimum capacity argument.
165     *
166 jsr166 1.5 * @param minCapacity the desired minimum capacity
167 dl 1.1 */
168     public void ensureCapacity(int minCapacity) {
169     modCount++;
170     if (minCapacity > elementData.length)
171     growArray(minCapacity);
172     }
173    
174     /**
175 jsr166 1.5 * Increases the capacity of the array.
176     *
177     * @param minCapacity the desired minimum capacity
178 dl 1.1 */
179     private void growArray(int minCapacity) {
180 jsr166 1.18 if (minCapacity < 0) // overflow
181     throw new OutOfMemoryError();
182 dl 1.1 int oldCapacity = elementData.length;
183 dl 1.19 // Double size if small; else grow by 50%
184     int newCapacity = ((oldCapacity < 64) ?
185     ((oldCapacity + 1) * 2) :
186     ((oldCapacity / 2) * 3));
187     if (newCapacity < 0) // overflow
188     newCapacity = Integer.MAX_VALUE;
189     if (newCapacity < minCapacity)
190     newCapacity = minCapacity;
191     elementData = Arrays.copyOf(elementData, newCapacity);
192 dl 1.1 }
193    
194     /**
195     * Returns the number of elements in this list.
196     *
197     * @return the number of elements in this list
198     */
199     public int size() {
200     return size;
201     }
202    
203     /**
204     * Returns <tt>true</tt> if this list contains no elements.
205     *
206     * @return <tt>true</tt> if this list contains no elements
207     */
208     public boolean isEmpty() {
209     return size == 0;
210     }
211    
212     /**
213     * Returns <tt>true</tt> if this list contains the specified element.
214     * More formally, returns <tt>true</tt> if and only if this list contains
215     * at least one element <tt>e</tt> such that
216     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
217     *
218     * @param o element whose presence in this list is to be tested
219     * @return <tt>true</tt> if this list contains the specified element
220     */
221     public boolean contains(Object o) {
222     return indexOf(o) >= 0;
223     }
224    
225     /**
226     * Returns the index of the first occurrence of the specified element
227     * in this list, or -1 if this list does not contain the element.
228     * More formally, returns the lowest index <tt>i</tt> such that
229     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
230     * or -1 if there is no such index.
231     */
232     public int indexOf(Object o) {
233     if (o == null) {
234     for (int i = 0; i < size; i++)
235     if (elementData[i]==null)
236     return i;
237     } else {
238     for (int i = 0; i < size; i++)
239     if (o.equals(elementData[i]))
240     return i;
241     }
242     return -1;
243     }
244    
245     /**
246     * Returns the index of the last occurrence of the specified element
247     * in this list, or -1 if this list does not contain the element.
248     * More formally, returns the highest index <tt>i</tt> such that
249     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
250     * or -1 if there is no such index.
251     */
252     public int lastIndexOf(Object o) {
253     if (o == null) {
254     for (int i = size-1; i >= 0; i--)
255     if (elementData[i]==null)
256     return i;
257     } else {
258     for (int i = size-1; i >= 0; i--)
259     if (o.equals(elementData[i]))
260     return i;
261     }
262     return -1;
263     }
264    
265     /**
266     * Returns a shallow copy of this <tt>ArrayList</tt> instance. (The
267     * elements themselves are not copied.)
268     *
269     * @return a clone of this <tt>ArrayList</tt> instance
270     */
271     public Object clone() {
272     try {
273     ArrayList<E> v = (ArrayList<E>) super.clone();
274     v.elementData = Arrays.copyOf(elementData, size);
275     v.modCount = 0;
276     return v;
277     } catch (CloneNotSupportedException e) {
278     // this shouldn't happen, since we are Cloneable
279     throw new InternalError();
280     }
281     }
282    
283     /**
284     * Returns an array containing all of the elements in this list
285     * in proper sequence (from first to last element).
286     *
287     * <p>The returned array will be "safe" in that no references to it are
288     * maintained by this list. (In other words, this method must allocate
289     * a new array). The caller is thus free to modify the returned array.
290     *
291     * <p>This method acts as bridge between array-based and collection-based
292     * APIs.
293     *
294     * @return an array containing all of the elements in this list in
295     * proper sequence
296     */
297     public Object[] toArray() {
298     return Arrays.copyOf(elementData, size);
299     }
300    
301     /**
302     * Returns an array containing all of the elements in this list in proper
303     * sequence (from first to last element); the runtime type of the returned
304     * array is that of the specified array. If the list fits in the
305     * specified array, it is returned therein. Otherwise, a new array is
306     * allocated with the runtime type of the specified array and the size of
307     * this list.
308     *
309     * <p>If the list fits in the specified array with room to spare
310     * (i.e., the array has more elements than the list), the element in
311     * the array immediately following the end of the collection is set to
312     * <tt>null</tt>. (This is useful in determining the length of the
313     * list <i>only</i> if the caller knows that the list does not contain
314     * any null elements.)
315     *
316     * @param a the array into which the elements of the list are to
317     * be stored, if it is big enough; otherwise, a new array of the
318     * same runtime type is allocated for this purpose.
319     * @return an array containing the elements of the list
320     * @throws ArrayStoreException if the runtime type of the specified array
321     * is not a supertype of the runtime type of every element in
322     * this list
323     * @throws NullPointerException if the specified array is null
324     */
325     public <T> T[] toArray(T[] a) {
326     if (a.length < size)
327     // Make a new array of a's runtime type, but my contents:
328     return (T[]) Arrays.copyOf(elementData, size, a.getClass());
329     System.arraycopy(elementData, 0, a, 0, size);
330     if (a.length > size)
331     a[size] = null;
332     return a;
333     }
334    
335     // Positional Access Operations
336    
337 jsr166 1.4 /**
338 dl 1.19 * Throws an appropriate exception for indexing errors.
339 dl 1.1 */
340 dl 1.19 private static void indexOutOfBounds(int i, int s) {
341     throw new IndexOutOfBoundsException("Index: " + i + ", Size: " + s);
342 dl 1.1 }
343    
344     /**
345     * Returns the element at the specified position in this list.
346     *
347     * @param index index of the element to return
348     * @return the element at the specified position in this list
349     * @throws IndexOutOfBoundsException {@inheritDoc}
350     */
351     public E get(int index) {
352     if (index >= size)
353 dl 1.19 indexOutOfBounds(index, size);
354     return (E) elementData[index];
355 dl 1.1 }
356    
357     /**
358     * Replaces the element at the specified position in this list with
359     * the specified element.
360     *
361     * @param index index of the element to replace
362     * @param element element to be stored at the specified position
363     * @return the element previously at the specified position
364     * @throws IndexOutOfBoundsException {@inheritDoc}
365     */
366     public E set(int index, E element) {
367     if (index >= size)
368 dl 1.19 indexOutOfBounds(index, size);
369 dl 1.1 E oldValue = (E) elementData[index];
370     elementData[index] = element;
371     return oldValue;
372     }
373    
374     /**
375     * Appends the specified element to the end of this list.
376     *
377     * @param e element to be appended to this list
378     * @return <tt>true</tt> (as specified by {@link Collection#add})
379     */
380     public boolean add(E e) {
381 jsr166 1.8 modCount++;
382 dl 1.7 int s = size;
383 dl 1.1 if (s >= elementData.length)
384     growArray(s + 1);
385     elementData[s] = e;
386 dl 1.19 size = s + 1;
387     return true;
388 dl 1.1 }
389    
390     /**
391     * Inserts the specified element at the specified position in this
392     * list. Shifts the element currently at that position (if any) and
393     * any subsequent elements to the right (adds one to their indices).
394     *
395     * @param index index at which the specified element is to be inserted
396     * @param element element to be inserted
397     * @throws IndexOutOfBoundsException {@inheritDoc}
398     */
399     public void add(int index, E element) {
400     int s = size;
401     if (index > s || index < 0)
402 dl 1.19 indexOutOfBounds(index, s);
403 jsr166 1.8 modCount++;
404 dl 1.1 if (s >= elementData.length)
405     growArray(s + 1);
406 jsr166 1.10 System.arraycopy(elementData, index,
407 dl 1.19 elementData, index + 1, s - index);
408 dl 1.1 elementData[index] = element;
409 dl 1.7 size = s + 1;
410 dl 1.1 }
411    
412     /**
413     * Removes the element at the specified position in this list.
414     * Shifts any subsequent elements to the left (subtracts one from their
415     * indices).
416     *
417     * @param index the index of the element to be removed
418     * @return the element that was removed from the list
419     * @throws IndexOutOfBoundsException {@inheritDoc}
420     */
421     public E remove(int index) {
422     int s = size - 1;
423 jsr166 1.8 if (index > s)
424 dl 1.19 indexOutOfBounds(index, size);
425 dl 1.1 modCount++;
426 dl 1.19 E oldValue = (E) elementData[index];
427 dl 1.1 int numMoved = s - index;
428     if (numMoved > 0)
429 jsr166 1.10 System.arraycopy(elementData, index + 1,
430 dl 1.19 elementData, index, numMoved);
431 jsr166 1.8 elementData[s] = null;
432 dl 1.19 size = s;
433 dl 1.7 return oldValue;
434 dl 1.1 }
435    
436     /**
437     * Removes the first occurrence of the specified element from this list,
438     * if it is present. If the list does not contain the element, it is
439     * unchanged. More formally, removes the element with the lowest index
440     * <tt>i</tt> such that
441     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
442     * (if such an element exists). Returns <tt>true</tt> if this list
443     * contained the specified element (or equivalently, if this list
444     * changed as a result of the call).
445     *
446     * @param o element to be removed from this list, if present
447     * @return <tt>true</tt> if this list contained the specified element
448     */
449     public boolean remove(Object o) {
450     if (o == null) {
451     for (int index = 0; index < size; index++)
452     if (elementData[index] == null) {
453     fastRemove(index);
454     return true;
455     }
456     } else {
457     for (int index = 0; index < size; index++)
458     if (o.equals(elementData[index])) {
459     fastRemove(index);
460     return true;
461     }
462     }
463     return false;
464     }
465    
466     /*
467     * Private remove method that skips bounds checking and does not
468     * return the value removed.
469     */
470     private void fastRemove(int index) {
471     modCount++;
472     int numMoved = size - index - 1;
473     if (numMoved > 0)
474     System.arraycopy(elementData, index+1, elementData, index,
475     numMoved);
476     elementData[--size] = null; // Let gc do its work
477     }
478    
479     /**
480     * Removes all of the elements from this list. The list will
481     * be empty after this call returns.
482     */
483     public void clear() {
484     modCount++;
485    
486     // Let gc do its work
487     for (int i = 0; i < size; i++)
488     elementData[i] = null;
489    
490     size = 0;
491     }
492    
493     /**
494     * Appends all of the elements in the specified collection to the end of
495     * this list, in the order that they are returned by the
496     * specified collection's Iterator. The behavior of this operation is
497     * undefined if the specified collection is modified while the operation
498     * is in progress. (This implies that the behavior of this call is
499     * undefined if the specified collection is this list, and this
500     * list is nonempty.)
501     *
502     * @param c collection containing elements to be added to this list
503     * @return <tt>true</tt> if this list changed as a result of the call
504     * @throws NullPointerException if the specified collection is null
505     */
506     public boolean addAll(Collection<? extends E> c) {
507     Object[] a = c.toArray();
508     int numNew = a.length;
509     ensureCapacity(size + numNew); // Increments modCount
510     System.arraycopy(a, 0, elementData, size, numNew);
511     size += numNew;
512     return numNew != 0;
513     }
514    
515     /**
516     * Inserts all of the elements in the specified collection into this
517     * list, starting at the specified position. Shifts the element
518     * currently at that position (if any) and any subsequent elements to
519     * the right (increases their indices). The new elements will appear
520     * in the list in the order that they are returned by the
521     * specified collection's iterator.
522     *
523     * @param index index at which to insert the first element from the
524     * specified collection
525     * @param c collection containing elements to be added to this list
526     * @return <tt>true</tt> if this list changed as a result of the call
527     * @throws IndexOutOfBoundsException {@inheritDoc}
528     * @throws NullPointerException if the specified collection is null
529     */
530     public boolean addAll(int index, Collection<? extends E> c) {
531     if (index > size || index < 0)
532 dl 1.19 indexOutOfBounds(index, size);
533 dl 1.1
534     Object[] a = c.toArray();
535     int numNew = a.length;
536     ensureCapacity(size + numNew); // Increments modCount
537    
538     int numMoved = size - index;
539     if (numMoved > 0)
540     System.arraycopy(elementData, index, elementData, index + numNew,
541     numMoved);
542    
543     System.arraycopy(a, 0, elementData, index, numNew);
544     size += numNew;
545     return numNew != 0;
546     }
547    
548     /**
549     * Removes from this list all of the elements whose index is between
550     * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
551     * Shifts any succeeding elements to the left (reduces their index).
552     * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
553     * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
554     *
555     * @param fromIndex index of first element to be removed
556     * @param toIndex index after last element to be removed
557     * @throws IndexOutOfBoundsException if fromIndex or toIndex out of
558     * range (fromIndex &lt; 0 || fromIndex &gt;= size() || toIndex
559     * &gt; size() || toIndex &lt; fromIndex)
560     */
561     protected void removeRange(int fromIndex, int toIndex) {
562     modCount++;
563     int numMoved = size - toIndex;
564     System.arraycopy(elementData, toIndex, elementData, fromIndex,
565     numMoved);
566    
567     // Let gc do its work
568     int newSize = size - (toIndex-fromIndex);
569     while (size != newSize)
570     elementData[--size] = null;
571     }
572    
573     /**
574     * Save the state of the <tt>ArrayList</tt> instance to a stream (that
575     * is, serialize it).
576     *
577     * @serialData The length of the array backing the <tt>ArrayList</tt>
578     * instance is emitted (int), followed by all of its elements
579     * (each an <tt>Object</tt>) in the proper order.
580     */
581     private void writeObject(java.io.ObjectOutputStream s)
582     throws java.io.IOException{
583     // Write out element count, and any hidden stuff
584     int expectedModCount = modCount;
585     s.defaultWriteObject();
586    
587     // Write out array length
588     s.writeInt(elementData.length);
589    
590     // Write out all elements in the proper order.
591     for (int i=0; i<size; i++)
592     s.writeObject(elementData[i]);
593    
594 jsr166 1.12 if (expectedModCount != modCount) {
595 dl 1.1 throw new ConcurrentModificationException();
596     }
597    
598     }
599    
600     /**
601     * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
602     * deserialize it).
603     */
604     private void readObject(java.io.ObjectInputStream s)
605     throws java.io.IOException, ClassNotFoundException {
606     // Read in size, and any hidden stuff
607     s.defaultReadObject();
608    
609     // Read in array length and allocate array
610     int arrayLength = s.readInt();
611     Object[] a = elementData = new Object[arrayLength];
612    
613     // Read in all elements in the proper order.
614     for (int i=0; i<size; i++)
615     a[i] = s.readObject();
616     }
617     }