ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.22
Committed: Thu Jan 15 15:10:31 2004 UTC (20 years, 4 months ago) by tim
Branch: MAIN
Changes since 1.21: +8 -8 lines
Log Message:
fixed signatures to match java.util

File Contents

# User Rev Content
1 dl 1.2 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3 dl 1.17 * Expert Group. Adapted and released, under explicit permission,
4 dl 1.15 * from JDK ArrayList.java which carries the following copyright:
5 dl 1.3 *
6     * Copyright 1997 by Sun Microsystems, Inc.,
7     * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
8     * All rights reserved.
9     *
10     * This software is the confidential and proprietary information
11     * of Sun Microsystems, Inc. ("Confidential Information"). You
12     * shall not disclose such Confidential Information and shall use
13     * it only in accordance with the terms of the license agreement
14     * you entered into with Sun.
15 dl 1.2 */
16    
17 tim 1.1 package java.util.concurrent;
18     import java.util.*;
19    
20     /**
21 dl 1.4 * A variant of {@link java.util.ArrayList} in which all mutative
22     * operations (add, set, and so on) are implemented by making a fresh
23     * copy of the underlying array. <p>
24 tim 1.1 *
25 dl 1.12 * This is ordinarily too costly, but may be <em>more</em> efficient
26     * than alternatives when traversal operations vastly outnumber
27     * mutations, and is useful when you cannot or don't want to
28     * synchronize traversals, yet need to preclude interference among
29 dl 1.15 * concurrent threads. The "snapshot" style iterator method uses a
30     * reference to the state of the array at the point that the iterator
31     * was created. This array never changes during the lifetime of the
32     * iterator, so interference is impossible and the iterator is
33     * guaranteed not to throw <tt>ConcurrentModificationException</tt>.
34     * The iterator will not reflect additions, removals, or changes to
35     * the list since the iterator was created. Element-changing
36     * operations on iterators themselves (remove, set, and add) are not
37     * supported. These methods throw
38     * <tt>UnsupportedOperationException</tt>.
39 dl 1.6 * @since 1.5
40     * @author Doug Lea
41 dl 1.19 * @param <E> the type of elements held in this collection
42 dl 1.6 */
43 tim 1.1 public class CopyOnWriteArrayList<E>
44     implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
45 dl 1.11 private static final long serialVersionUID = 8673264195747942595L;
46 tim 1.1
47     /**
48 dl 1.6 * The held array. Directly accessed only within synchronized
49 tim 1.1 * methods
50     */
51 dl 1.12 private volatile transient E[] array;
52 tim 1.1
53     /**
54     * Accessor to the array intended to be called from
55     * within unsynchronized read-only methods
56     **/
57 dl 1.12 private E[] array() { return array; }
58 tim 1.1
59     /**
60 dl 1.15 * Creates an empty list.
61 tim 1.1 */
62     public CopyOnWriteArrayList() {
63 dl 1.12 array = (E[]) new Object[0];
64 tim 1.1 }
65    
66     /**
67 dl 1.15 * Creates a list containing the elements of the specified
68 tim 1.1 * Collection, in the order they are returned by the Collection's
69     * iterator.
70 dl 1.6 * @param c the collection of initially held elements
71 tim 1.1 */
72 tim 1.22 public CopyOnWriteArrayList(Collection<? extends E> c) {
73 dl 1.12 array = (E[]) new Object[c.size()];
74 tim 1.22 Iterator<? extends E> i = c.iterator();
75 tim 1.1 int size = 0;
76     while (i.hasNext())
77 dl 1.12 array[size++] = i.next();
78 tim 1.1 }
79    
80     /**
81 tim 1.9 * Create a new CopyOnWriteArrayList holding a copy of given array.
82     *
83     * @param toCopyIn the array (a copy of this array is used as the
84     * internal array)
85 tim 1.1 **/
86     public CopyOnWriteArrayList(E[] toCopyIn) {
87     copyIn(toCopyIn, 0, toCopyIn.length);
88     }
89    
90     /**
91 dl 1.14 * Replace the held array with a copy of the <tt>n</tt>
92 dl 1.12 * elements of the provided array, starting at position
93 dl 1.14 * <tt>first</tt>. To copy an entire array, call with
94 dl 1.12 * arguments (array, 0, array.length).
95 tim 1.1 * @param toCopyIn the array. A copy of the indicated elements of
96     * this array is used as the
97     * internal array.
98     * @param first The index of first position of the array to
99     * start copying from.
100     * @param n the number of elements to copy. This will be the new size of
101     * the list.
102     **/
103     private synchronized void copyIn(E[] toCopyIn, int first, int n) {
104 dl 1.12 array = (E[]) new Object[n];
105     System.arraycopy(toCopyIn, first, array, 0, n);
106 tim 1.1 }
107    
108     /**
109 dl 1.15 * Returns the number of elements in this list.
110 tim 1.1 *
111 dl 1.15 * @return the number of elements in this list.
112 tim 1.1 */
113     public int size() {
114     return array().length;
115     }
116    
117     /**
118 dl 1.15 * Tests if this list has no elements.
119 tim 1.1 *
120 dl 1.15 * @return <tt>true</tt> if this list has no elements;
121 dl 1.14 * <tt>false</tt> otherwise.
122 tim 1.1 */
123     public boolean isEmpty() {
124     return size() == 0;
125     }
126    
127     /**
128 dl 1.15 * Returns <tt>true</tt> if this list contains the specified element.
129 tim 1.1 *
130 dl 1.6 * @param elem element whose presence in this List is to be tested.
131 dl 1.15 * @return <code>true</code> if the specified element is present;
132 tim 1.22 * <code>false</code> otherwise.
133 tim 1.1 */
134     public boolean contains(Object elem) {
135     E[] elementData = array();
136     int len = elementData.length;
137     return indexOf(elem, elementData, len) >= 0;
138     }
139    
140     /**
141 dl 1.16 * Searches for the first occurrence of the given argument, testing
142 dl 1.15 * for equality using the <tt>equals</tt> method.
143 tim 1.1 *
144     * @param elem an object.
145     * @return the index of the first occurrence of the argument in this
146 dl 1.14 * list; returns <tt>-1</tt> if the object is not found.
147 tim 1.1 * @see Object#equals(Object)
148     */
149     public int indexOf(Object elem) {
150     E[] elementData = array();
151     int len = elementData.length;
152     return indexOf(elem, elementData, len);
153     }
154    
155     /**
156     * static version allows repeated call without needed
157     * to grab lock for array each time
158     **/
159     private static int indexOf(Object elem, Object[] elementData, int len) {
160     if (elem == null) {
161     for (int i = 0; i < len; i++)
162     if (elementData[i]==null)
163     return i;
164     } else {
165     for (int i = 0; i < len; i++)
166     if (elem.equals(elementData[i]))
167     return i;
168     }
169     return -1;
170     }
171    
172     /**
173 dl 1.16 * Searches for the first occurrence of the given argument, beginning
174 dl 1.14 * the search at <tt>index</tt>, and testing for equality using
175     * the <tt>equals</tt> method.
176 tim 1.1 *
177     * @param elem an object.
178     * @param index the index to start searching from.
179     * @return the index of the first occurrence of the object argument in
180 dl 1.14 * this List at position <tt>index</tt> or later in the
181     * List; returns <tt>-1</tt> if the object is not found.
182 tim 1.1 * @see Object#equals(Object)
183     */
184     public int indexOf(E elem, int index) {
185     E[] elementData = array();
186     int elementCount = elementData.length;
187    
188     if (elem == null) {
189     for (int i = index ; i < elementCount ; i++)
190     if (elementData[i]==null)
191     return i;
192     } else {
193     for (int i = index ; i < elementCount ; i++)
194     if (elem.equals(elementData[i]))
195     return i;
196     }
197     return -1;
198     }
199    
200     /**
201     * Returns the index of the last occurrence of the specified object in
202     * this list.
203     *
204 dl 1.15 * @param elem the desired element.
205 tim 1.1 * @return the index of the last occurrence of the specified object in
206     * this list; returns -1 if the object is not found.
207     */
208     public int lastIndexOf(Object elem) {
209     E[] elementData = array();
210     int len = elementData.length;
211     return lastIndexOf(elem, elementData, len);
212     }
213    
214     private static int lastIndexOf(Object elem, Object[] elementData, int len) {
215     if (elem == null) {
216     for (int i = len-1; i >= 0; i--)
217     if (elementData[i]==null)
218     return i;
219     } else {
220     for (int i = len-1; i >= 0; i--)
221     if (elem.equals(elementData[i]))
222     return i;
223     }
224     return -1;
225     }
226    
227     /**
228     * Searches backwards for the specified object, starting from the
229     * specified index, and returns an index to it.
230     *
231 dl 1.15 * @param elem the desired element.
232 tim 1.1 * @param index the index to start searching from.
233     * @return the index of the last occurrence of the specified object in this
234     * List at position less than index in the List;
235     * -1 if the object is not found.
236     */
237     public int lastIndexOf(E elem, int index) {
238     // needed in order to compile on 1.2b3
239     E[] elementData = array();
240     if (elem == null) {
241     for (int i = index; i >= 0; i--)
242     if (elementData[i]==null)
243     return i;
244     } else {
245     for (int i = index; i >= 0; i--)
246     if (elem.equals(elementData[i]))
247     return i;
248     }
249     return -1;
250     }
251    
252     /**
253     * Returns a shallow copy of this list. (The elements themselves
254     * are not copied.)
255     *
256     * @return a clone of this list.
257     */
258     public Object clone() {
259     try {
260     E[] elementData = array();
261 tim 1.8 CopyOnWriteArrayList<E> v = (CopyOnWriteArrayList<E>)super.clone();
262 dl 1.12 v.array = (E[]) new Object[elementData.length];
263     System.arraycopy(elementData, 0, v.array, 0, elementData.length);
264 tim 1.1 return v;
265     } catch (CloneNotSupportedException e) {
266     // this shouldn't happen, since we are Cloneable
267     throw new InternalError();
268     }
269     }
270    
271     /**
272     * Returns an array containing all of the elements in this list
273     * in the correct order.
274 dl 1.15 * @return an array containing all of the elements in this list
275 tim 1.22 * in the correct order.
276 tim 1.1 */
277     public Object[] toArray() {
278     Object[] elementData = array();
279     Object[] result = new Object[elementData.length];
280     System.arraycopy(elementData, 0, result, 0, elementData.length);
281     return result;
282     }
283    
284     /**
285     * Returns an array containing all of the elements in this list in the
286     * correct order. The runtime type of the returned array is that of the
287     * specified array. If the list fits in the specified array, it is
288     * returned therein. Otherwise, a new array is allocated with the runtime
289     * type of the specified array and the size of this list.
290     * <p>
291     * If the list fits in the specified array with room to spare
292     * (i.e., the array has more elements than the list),
293     * the element in the array immediately following the end of the
294     * collection is set to null. This is useful in determining the length
295     * of the list <em>only</em> if the caller knows that the list
296     * does not contain any null elements.
297     *
298     * @param a the array into which the elements of the list are to
299     * be stored, if it is big enough; otherwise, a new array of the
300     * same runtime type is allocated for this purpose.
301     * @return an array containing the elements of the list.
302 dl 1.6 * @throws ArrayStoreException the runtime type of a is not a supertype
303 tim 1.1 * of the runtime type of every element in this list.
304     */
305     public <T> T[] toArray(T a[]) {
306     E[] elementData = array();
307    
308     if (a.length < elementData.length)
309     a = (T[])
310     java.lang.reflect.Array.newInstance(a.getClass().getComponentType(),
311     elementData.length);
312    
313     System.arraycopy(elementData, 0, a, 0, elementData.length);
314    
315     if (a.length > elementData.length)
316     a[elementData.length] = null;
317    
318     return a;
319     }
320    
321     // Positional Access Operations
322    
323     /**
324     * Returns the element at the specified position in this list.
325     *
326 dl 1.15 * @param index index of element to return.
327     * @return the element at the specified position in this list.
328     * @throws IndexOutOfBoundsException if index is out of range <tt>(index
329 tim 1.22 * &lt; 0 || index &gt;= size())</tt>.
330 tim 1.1 */
331     public E get(int index) {
332     E[] elementData = array();
333     rangeCheck(index, elementData.length);
334     return elementData[index];
335     }
336    
337     /**
338     * Replaces the element at the specified position in this list with
339     * the specified element.
340     *
341     * @param index index of element to replace.
342     * @param element element to be stored at the specified position.
343     * @return the element previously at the specified position.
344 dl 1.15 * @throws IndexOutOfBoundsException if index out of range
345 tim 1.22 * <tt>(index &lt; 0 || index &gt;= size())</tt>.
346 tim 1.1 */
347     public synchronized E set(int index, E element) {
348 dl 1.12 int len = array.length;
349 tim 1.1 rangeCheck(index, len);
350 dl 1.12 E oldValue = array[index];
351 tim 1.1
352     boolean same = (oldValue == element ||
353     (element != null && element.equals(oldValue)));
354     if (!same) {
355 tim 1.7 E[] newArray = (E[]) new Object[len];
356 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
357 tim 1.1 newArray[index] = element;
358 dl 1.12 array = newArray;
359 tim 1.1 }
360     return oldValue;
361     }
362    
363     /**
364     * Appends the specified element to the end of this list.
365     *
366     * @param element element to be appended to this list.
367     * @return true (as per the general contract of Collection.add).
368     */
369     public synchronized boolean add(E element) {
370 dl 1.12 int len = array.length;
371 tim 1.7 E[] newArray = (E[]) new Object[len+1];
372 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
373 tim 1.1 newArray[len] = element;
374 dl 1.12 array = newArray;
375 tim 1.1 return true;
376     }
377    
378     /**
379     * Inserts the specified element at the specified position in this
380     * list. Shifts the element currently at that position (if any) and
381     * any subsequent elements to the right (adds one to their indices).
382     *
383     * @param index index at which the specified element is to be inserted.
384     * @param element element to be inserted.
385 dl 1.15 * @throws IndexOutOfBoundsException if index is out of range
386 tim 1.22 * <tt>(index &lt; 0 || index &gt; size())</tt>.
387 tim 1.1 */
388     public synchronized void add(int index, E element) {
389 dl 1.12 int len = array.length;
390 tim 1.1 if (index > len || index < 0)
391     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+len);
392    
393 tim 1.7 E[] newArray = (E[]) new Object[len+1];
394 dl 1.12 System.arraycopy(array, 0, newArray, 0, index);
395 tim 1.1 newArray[index] = element;
396 dl 1.12 System.arraycopy(array, index, newArray, index+1, len - index);
397     array = newArray;
398 tim 1.1 }
399    
400     /**
401     * Removes the element at the specified position in this list.
402     * Shifts any subsequent elements to the left (subtracts one from their
403 dl 1.15 * indices).
404 tim 1.1 *
405     * @param index the index of the element to removed.
406 dl 1.15 * @return the element that was removed from the list.
407     * @throws IndexOutOfBoundsException if index out of range <tt>(index
408 tim 1.22 * &lt; 0 || index &gt;= size())</tt>.
409 tim 1.1 */
410     public synchronized E remove(int index) {
411 dl 1.12 int len = array.length;
412 tim 1.1 rangeCheck(index, len);
413 dl 1.12 E oldValue = array[index];
414 tim 1.7 E[] newArray = (E[]) new Object[len-1];
415 dl 1.12 System.arraycopy(array, 0, newArray, 0, index);
416 tim 1.1 int numMoved = len - index - 1;
417     if (numMoved > 0)
418 dl 1.12 System.arraycopy(array, index+1, newArray, index, numMoved);
419     array = newArray;
420 tim 1.1 return oldValue;
421     }
422    
423     /**
424 dl 1.15 * Removes a single instance of the specified element from this
425     * list, if it is present (optional operation). More formally,
426     * removes an element <tt>e</tt> such that <tt>(o==null ? e==null :
427     * o.equals(e))</tt>, if the list contains one or more such
428     * elements. Returns <tt>true</tt> if the list contained the
429     * specified element (or equivalently, if the list changed as a
430     * result of the call).<p>
431 tim 1.1 *
432 dl 1.15 * @param o element to be removed from this list, if present.
433     * @return <tt>true</tt> if the list contained the specified element.
434 tim 1.1 */
435 dl 1.15 public synchronized boolean remove(Object o) {
436 dl 1.12 int len = array.length;
437 tim 1.1 if (len == 0) return false;
438    
439     // Copy while searching for element to remove
440     // This wins in the normal case of element being present
441    
442     int newlen = len-1;
443 tim 1.7 E[] newArray = (E[]) new Object[newlen];
444 tim 1.1
445     for (int i = 0; i < newlen; ++i) {
446 dl 1.15 if (o == array[i] ||
447     (o != null && o.equals(array[i]))) {
448 tim 1.1 // found one; copy remaining and exit
449 dl 1.12 for (int k = i + 1; k < len; ++k) newArray[k-1] = array[k];
450     array = newArray;
451 tim 1.1 return true;
452 tim 1.10 } else
453 dl 1.12 newArray[i] = array[i];
454 tim 1.1 }
455     // special handling for last cell
456    
457 dl 1.15 if (o == array[newlen] ||
458     (o != null && o.equals(array[newlen]))) {
459 dl 1.12 array = newArray;
460 tim 1.1 return true;
461 tim 1.10 } else
462 tim 1.1 return false; // throw away copy
463     }
464    
465    
466     /**
467     * Removes from this List all of the elements whose index is between
468     * fromIndex, inclusive and toIndex, exclusive. Shifts any succeeding
469     * elements to the left (reduces their index).
470 dl 1.15 * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
471     * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
472 tim 1.1 *
473     * @param fromIndex index of first element to be removed.
474 dl 1.6 * @param toIndex index after last element to be removed.
475     * @throws IndexOutOfBoundsException fromIndex or toIndex out of
476 tim 1.1 * range (fromIndex &lt; 0 || fromIndex &gt;= size() || toIndex
477     * &gt; size() || toIndex &lt; fromIndex).
478     */
479     private synchronized void removeRange(int fromIndex, int toIndex) {
480 dl 1.12 int len = array.length;
481 tim 1.1
482     if (fromIndex < 0 || fromIndex >= len ||
483     toIndex > len || toIndex < fromIndex)
484     throw new IndexOutOfBoundsException();
485    
486     int numMoved = len - toIndex;
487     int newlen = len - (toIndex-fromIndex);
488 tim 1.7 E[] newArray = (E[]) new Object[newlen];
489 dl 1.12 System.arraycopy(array, 0, newArray, 0, fromIndex);
490     System.arraycopy(array, toIndex, newArray, fromIndex, numMoved);
491     array = newArray;
492 tim 1.1 }
493    
494    
495     /**
496     * Append the element if not present.
497     * @param element element to be added to this Collection, if absent.
498     * @return true if added
499     **/
500     public synchronized boolean addIfAbsent(E element) {
501     // Copy while checking if already present.
502     // This wins in the most common case where it is not present
503 dl 1.12 int len = array.length;
504 tim 1.7 E[] newArray = (E[]) new Object[len + 1];
505 tim 1.1 for (int i = 0; i < len; ++i) {
506 dl 1.12 if (element == array[i] ||
507     (element != null && element.equals(array[i])))
508 tim 1.1 return false; // exit, throwing away copy
509     else
510 dl 1.12 newArray[i] = array[i];
511 tim 1.1 }
512     newArray[len] = element;
513 dl 1.12 array = newArray;
514 tim 1.1 return true;
515     }
516    
517     /**
518     * Returns true if this Collection contains all of the elements in the
519     * specified Collection.
520     * <p>
521     * This implementation iterates over the specified Collection, checking
522     * each element returned by the Iterator in turn to see if it's
523     * contained in this Collection. If all elements are so contained
524     * true is returned, otherwise false.
525 dl 1.6 * @param c the collection
526     * @return true if all elements are contained
527 tim 1.1 */
528 tim 1.7 public boolean containsAll(Collection<?> c) {
529 tim 1.1 E[] elementData = array();
530     int len = elementData.length;
531 tim 1.7 Iterator e = c.iterator();
532 tim 1.1 while (e.hasNext())
533 dl 1.20 if (indexOf(e.next(), elementData, len) < 0)
534 tim 1.1 return false;
535    
536     return true;
537     }
538    
539    
540     /**
541     * Removes from this Collection all of its elements that are contained in
542     * the specified Collection. This is a particularly expensive operation
543     * in this class because of the need for an internal temporary array.
544     * <p>
545     *
546 dl 1.6 * @param c the collection
547 tim 1.1 * @return true if this Collection changed as a result of the call.
548     */
549 tim 1.7 public synchronized boolean removeAll(Collection<?> c) {
550 dl 1.12 E[] elementData = array;
551 tim 1.1 int len = elementData.length;
552     if (len == 0) return false;
553    
554     // temp array holds those elements we know we want to keep
555 tim 1.7 E[] temp = (E[]) new Object[len];
556 tim 1.1 int newlen = 0;
557     for (int i = 0; i < len; ++i) {
558     E element = elementData[i];
559     if (!c.contains(element)) {
560     temp[newlen++] = element;
561     }
562     }
563    
564     if (newlen == len) return false;
565    
566     // copy temp as new array
567 tim 1.7 E[] newArray = (E[]) new Object[newlen];
568 tim 1.1 System.arraycopy(temp, 0, newArray, 0, newlen);
569 dl 1.12 array = newArray;
570 tim 1.1 return true;
571     }
572    
573     /**
574     * Retains only the elements in this Collection that are contained in the
575     * specified Collection (optional operation). In other words, removes from
576     * this Collection all of its elements that are not contained in the
577     * specified Collection.
578 dl 1.6 * @param c the collection
579 tim 1.1 * @return true if this Collection changed as a result of the call.
580     */
581 tim 1.7 public synchronized boolean retainAll(Collection<?> c) {
582 dl 1.12 E[] elementData = array;
583 tim 1.1 int len = elementData.length;
584     if (len == 0) return false;
585    
586 tim 1.7 E[] temp = (E[]) new Object[len];
587 tim 1.1 int newlen = 0;
588     for (int i = 0; i < len; ++i) {
589     E element = elementData[i];
590     if (c.contains(element)) {
591     temp[newlen++] = element;
592     }
593     }
594    
595     if (newlen == len) return false;
596    
597 tim 1.7 E[] newArray = (E[]) new Object[newlen];
598 tim 1.1 System.arraycopy(temp, 0, newArray, 0, newlen);
599 dl 1.12 array = newArray;
600 tim 1.1 return true;
601     }
602    
603     /**
604     * Appends all of the elements in the specified Collection that
605     * are not already contained in this list, to the end of
606     * this list, in the order that they are returned by the
607     * specified Collection's Iterator.
608     *
609     * @param c elements to be added into this list.
610     * @return the number of elements added
611     */
612 tim 1.7 public synchronized int addAllAbsent(Collection<? extends E> c) {
613 tim 1.1 int numNew = c.size();
614     if (numNew == 0) return 0;
615    
616 dl 1.12 E[] elementData = array;
617 tim 1.1 int len = elementData.length;
618    
619 tim 1.7 E[] temp = (E[]) new Object[numNew];
620 tim 1.1 int added = 0;
621 dl 1.20 Iterator<? extends E> e = c.iterator();
622 tim 1.1 while (e.hasNext()) {
623 dl 1.20 E element = e.next();
624 tim 1.1 if (indexOf(element, elementData, len) < 0) {
625     if (indexOf(element, temp, added) < 0) {
626     temp[added++] = element;
627     }
628     }
629     }
630    
631     if (added == 0) return 0;
632    
633 tim 1.7 E[] newArray = (E[]) new Object[len+added];
634 tim 1.1 System.arraycopy(elementData, 0, newArray, 0, len);
635     System.arraycopy(temp, 0, newArray, len, added);
636 dl 1.12 array = newArray;
637 tim 1.1 return added;
638     }
639    
640     /**
641     * Removes all of the elements from this list.
642     *
643     */
644     public synchronized void clear() {
645 dl 1.12 array = (E[]) new Object[0];
646 tim 1.1 }
647    
648     /**
649     * Appends all of the elements in the specified Collection to the end of
650     * this list, in the order that they are returned by the
651     * specified Collection's Iterator.
652     *
653     * @param c elements to be inserted into this list.
654 dl 1.6 * @return true if any elements are added
655 tim 1.1 */
656 tim 1.7 public synchronized boolean addAll(Collection<? extends E> c) {
657 tim 1.1 int numNew = c.size();
658     if (numNew == 0) return false;
659    
660 dl 1.12 int len = array.length;
661 tim 1.7 E[] newArray = (E[]) new Object[len+numNew];
662 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
663 dl 1.20 Iterator<? extends E> e = c.iterator();
664 tim 1.1 for (int i=0; i<numNew; i++)
665 dl 1.20 newArray[len++] = e.next();
666 dl 1.12 array = newArray;
667 tim 1.1
668     return true;
669     }
670    
671     /**
672     * Inserts all of the elements in the specified Collection into this
673     * list, starting at the specified position. Shifts the element
674     * currently at that position (if any) and any subsequent elements to
675     * the right (increases their indices). The new elements will appear
676     * in the list in the order that they are returned by the
677     * specified Collection's iterator.
678     *
679     * @param index index at which to insert first element
680     * from the specified collection.
681     * @param c elements to be inserted into this list.
682 dl 1.6 * @throws IndexOutOfBoundsException index out of range (index
683 tim 1.1 * &lt; 0 || index &gt; size()).
684 dl 1.6 * @return true if any elements are added
685 tim 1.1 */
686 tim 1.7 public synchronized boolean addAll(int index, Collection<? extends E> c) {
687 dl 1.12 int len = array.length;
688 tim 1.1 if (index > len || index < 0)
689     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+len);
690    
691     int numNew = c.size();
692     if (numNew == 0) return false;
693    
694 tim 1.7 E[] newArray = (E[]) new Object[len+numNew];
695 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
696 tim 1.1 int numMoved = len - index;
697     if (numMoved > 0)
698 dl 1.12 System.arraycopy(array, index, newArray, index + numNew, numMoved);
699 dl 1.20 Iterator<? extends E> e = c.iterator();
700 tim 1.1 for (int i=0; i<numNew; i++)
701 dl 1.20 newArray[index++] = e.next();
702 dl 1.12 array = newArray;
703 tim 1.1
704     return true;
705     }
706    
707     /**
708     * Check if the given index is in range. If not, throw an appropriate
709     * runtime exception.
710     */
711     private void rangeCheck(int index, int length) {
712     if (index >= length || index < 0)
713     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+ length);
714     }
715    
716     /**
717     * Save the state of the list to a stream (i.e., serialize it).
718     *
719     * @serialData The length of the array backing the list is emitted
720     * (int), followed by all of its elements (each an Object)
721     * in the proper order.
722 dl 1.6 * @param s the stream
723 tim 1.1 */
724     private void writeObject(java.io.ObjectOutputStream s)
725     throws java.io.IOException{
726    
727     // Write out element count, and any hidden stuff
728     s.defaultWriteObject();
729    
730     E[] elementData = array();
731     // Write out array length
732     s.writeInt(elementData.length);
733    
734     // Write out all elements in the proper order.
735     for (int i=0; i<elementData.length; i++)
736     s.writeObject(elementData[i]);
737     }
738    
739     /**
740     * Reconstitute the list from a stream (i.e., deserialize it).
741 dl 1.6 * @param s the stream
742 tim 1.1 */
743 dl 1.12 private void readObject(java.io.ObjectInputStream s)
744 tim 1.1 throws java.io.IOException, ClassNotFoundException {
745    
746     // Read in size, and any hidden stuff
747     s.defaultReadObject();
748    
749     // Read in array length and allocate array
750     int arrayLength = s.readInt();
751 tim 1.7 E[] elementData = (E[]) new Object[arrayLength];
752 tim 1.1
753     // Read in all elements in the proper order.
754     for (int i=0; i<elementData.length; i++)
755     elementData[i] = (E) s.readObject();
756 dl 1.12 array = elementData;
757 tim 1.1 }
758    
759     /**
760     * Returns a string representation of this Collection, containing
761     * the String representation of each element.
762     */
763     public String toString() {
764     StringBuffer buf = new StringBuffer();
765     Iterator e = iterator();
766     buf.append("[");
767     int maxIndex = size() - 1;
768     for (int i = 0; i <= maxIndex; i++) {
769     buf.append(String.valueOf(e.next()));
770     if (i < maxIndex)
771     buf.append(", ");
772     }
773     buf.append("]");
774     return buf.toString();
775     }
776    
777    
778     /**
779     * Compares the specified Object with this List for equality. Returns true
780     * if and only if the specified Object is also a List, both Lists have the
781     * same size, and all corresponding pairs of elements in the two Lists are
782 dl 1.14 * <em>equal</em>. (Two elements <tt>e1</tt> and <tt>e2</tt> are
783     * <em>equal</em> if <tt>(e1==null ? e2==null : e1.equals(e2))</tt>.)
784 tim 1.1 * In other words, two Lists are defined to be equal if they contain the
785     * same elements in the same order.
786     * <p>
787     * This implementation first checks if the specified object is this
788     * List. If so, it returns true; if not, it checks if the specified
789     * object is a List. If not, it returns false; if so, it iterates over
790     * both lists, comparing corresponding pairs of elements. If any
791     * comparison returns false, this method returns false. If either
792     * Iterator runs out of elements before before the other it returns false
793     * (as the Lists are of unequal length); otherwise it returns true when
794     * the iterations complete.
795     *
796     * @param o the Object to be compared for equality with this List.
797     * @return true if the specified Object is equal to this List.
798     */
799     public boolean equals(Object o) {
800     if (o == this)
801     return true;
802     if (!(o instanceof List))
803     return false;
804    
805 tim 1.8 List<E> l2 = (List<E>)(o);
806 tim 1.1 if (size() != l2.size())
807     return false;
808    
809     ListIterator<E> e1 = listIterator();
810     ListIterator<E> e2 = l2.listIterator();
811     while(e1.hasNext()) {
812     E o1 = e1.next();
813     E o2 = e2.next();
814     if (!(o1==null ? o2==null : o1.equals(o2)))
815     return false;
816     }
817     return true;
818     }
819    
820     /**
821 dl 1.15 * Returns the hash code value for this List. <p> This
822     * implementation uses the definition in {@link List#hashCode}.
823     * @return the hash code
824 tim 1.1 */
825     public int hashCode() {
826     int hashCode = 1;
827     Iterator<E> i = iterator();
828     while (i.hasNext()) {
829     E obj = i.next();
830     hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
831     }
832     return hashCode;
833     }
834    
835     /**
836     * Returns an Iterator over the elements contained in this collection.
837     * The iterator provides a snapshot of the state of the list
838     * when the iterator was constructed. No synchronization is
839     * needed while traversing the iterator. The iterator does
840 dl 1.14 * <em>NOT</em> support the <tt>remove</tt> method.
841 tim 1.1 */
842     public Iterator<E> iterator() {
843     return new COWIterator<E>(array(), 0);
844     }
845    
846     /**
847     * Returns an Iterator of the elements in this List (in proper sequence).
848     * The iterator provides a snapshot of the state of the list
849     * when the iterator was constructed. No synchronization is
850     * needed while traversing the iterator. The iterator does
851 dl 1.14 * <em>NOT</em> support the <tt>remove</tt>, <tt>set</tt>,
852     * or <tt>add</tt> methods.
853 tim 1.1 *
854     */
855     public ListIterator<E> listIterator() {
856     return new COWIterator<E>(array(), 0);
857     }
858    
859     /**
860     * Returns a ListIterator of the elements in this List (in proper
861     * sequence), starting at the specified position in the List. The
862     * specified index indicates the first element that would be returned by
863     * an initial call to nextElement. An initial call to previousElement
864     * would return the element with the specified index minus one.
865     * The ListIterator returned by this implementation will throw
866     * an UnsupportedOperationException in its remove, set and
867     * add methods.
868     *
869     * @param index index of first element to be returned from the
870     * ListIterator (by a call to getNext).
871 dl 1.6 * @throws IndexOutOfBoundsException index is out of range
872 tim 1.1 * (index &lt; 0 || index &gt; size()).
873     */
874     public ListIterator<E> listIterator(final int index) {
875     E[] elementData = array();
876     int len = elementData.length;
877     if (index<0 || index>len)
878     throw new IndexOutOfBoundsException("Index: "+index);
879    
880     return new COWIterator<E>(array(), index);
881     }
882    
883     private static class COWIterator<E> implements ListIterator<E> {
884    
885     /** Snapshot of the array **/
886     private final E[] array;
887    
888     /**
889     * Index of element to be returned by subsequent call to next.
890     */
891     private int cursor;
892    
893     private COWIterator(E[] elementArray, int initialCursor) {
894     array = elementArray;
895     cursor = initialCursor;
896     }
897    
898     public boolean hasNext() {
899     return cursor < array.length;
900     }
901    
902     public boolean hasPrevious() {
903     return cursor > 0;
904     }
905    
906     public E next() {
907     try {
908     return array[cursor++];
909 tim 1.10 } catch (IndexOutOfBoundsException ex) {
910 tim 1.1 throw new NoSuchElementException();
911     }
912     }
913    
914     public E previous() {
915     try {
916     return array[--cursor];
917     } catch(IndexOutOfBoundsException e) {
918     throw new NoSuchElementException();
919     }
920     }
921    
922     public int nextIndex() {
923     return cursor;
924     }
925    
926     public int previousIndex() {
927     return cursor-1;
928     }
929    
930     /**
931     * Not supported. Always throws UnsupportedOperationException.
932 dl 1.6 * @throws UnsupportedOperationException remove is not supported
933 tim 1.1 * by this Iterator.
934     */
935    
936     public void remove() {
937     throw new UnsupportedOperationException();
938     }
939    
940     /**
941     * Not supported. Always throws UnsupportedOperationException.
942 dl 1.6 * @throws UnsupportedOperationException set is not supported
943 tim 1.1 * by this Iterator.
944     */
945     public void set(E o) {
946     throw new UnsupportedOperationException();
947     }
948    
949     /**
950     * Not supported. Always throws UnsupportedOperationException.
951 dl 1.6 * @throws UnsupportedOperationException add is not supported
952 tim 1.1 * by this Iterator.
953     */
954     public void add(E o) {
955     throw new UnsupportedOperationException();
956     }
957     }
958    
959    
960     /**
961     * Returns a view of the portion of this List between fromIndex,
962     * inclusive, and toIndex, exclusive. The returned List is backed by this
963     * List, so changes in the returned List are reflected in this List, and
964     * vice-versa. While mutative operations are supported, they are
965 dl 1.16 * probably not very useful for CopyOnWriteArrayLists.
966 tim 1.9 * <p>
967 tim 1.1 * The semantics of the List returned by this method become undefined if
968     * the backing list (i.e., this List) is <i>structurally modified</i> in
969     * any way other than via the returned List. (Structural modifications are
970     * those that change the size of the List, or otherwise perturb it in such
971     * a fashion that iterations in progress may yield incorrect results.)
972     *
973     * @param fromIndex low endpoint (inclusive) of the subList.
974 dl 1.6 * @param toIndex high endpoint (exclusive) of the subList.
975 tim 1.1 * @return a view of the specified range within this List.
976 dl 1.6 * @throws IndexOutOfBoundsException Illegal endpoint index value
977 tim 1.1 * (fromIndex &lt; 0 || toIndex &gt; size || fromIndex &gt; toIndex).
978     */
979     public synchronized List<E> subList(int fromIndex, int toIndex) {
980 dl 1.21 // synchronized since sublist constructor depends on it.
981 dl 1.12 int len = array.length;
982 tim 1.1 if (fromIndex<0 || toIndex>len || fromIndex>toIndex)
983     throw new IndexOutOfBoundsException();
984     return new COWSubList<E>(this, fromIndex, toIndex);
985     }
986    
987     private static class COWSubList<E> extends AbstractList<E> {
988    
989     /*
990 dl 1.2 This class extends AbstractList merely for convenience, to
991     avoid having to define addAll, etc. This doesn't hurt, but
992     is wasteful. This class does not need or use modCount
993     mechanics in AbstractList, but does need to check for
994     concurrent modification using similar mechanics. On each
995     operation, the array that we expect the backing list to use
996     is checked and updated. Since we do this for all of the
997     base operations invoked by those defined in AbstractList,
998     all is well. While inefficient, this is not worth
999     improving. The kinds of list operations inherited from
1000 dl 1.20 AbstractList are already so slow on COW sublists that
1001 dl 1.2 adding a bit more space/time doesn't seem even noticeable.
1002 tim 1.1 */
1003    
1004     private final CopyOnWriteArrayList<E> l;
1005     private final int offset;
1006     private int size;
1007     private E[] expectedArray;
1008    
1009     private COWSubList(CopyOnWriteArrayList<E> list,
1010     int fromIndex, int toIndex) {
1011     l = list;
1012     expectedArray = l.array();
1013     offset = fromIndex;
1014     size = toIndex - fromIndex;
1015     }
1016    
1017     // only call this holding l's lock
1018     private void checkForComodification() {
1019 dl 1.12 if (l.array != expectedArray)
1020 tim 1.1 throw new ConcurrentModificationException();
1021     }
1022    
1023     // only call this holding l's lock
1024     private void rangeCheck(int index) {
1025     if (index<0 || index>=size)
1026     throw new IndexOutOfBoundsException("Index: "+index+ ",Size: "+size);
1027     }
1028    
1029    
1030     public E set(int index, E element) {
1031     synchronized(l) {
1032     rangeCheck(index);
1033     checkForComodification();
1034     E x = l.set(index+offset, element);
1035 dl 1.12 expectedArray = l.array;
1036 tim 1.1 return x;
1037     }
1038     }
1039    
1040     public E get(int index) {
1041     synchronized(l) {
1042     rangeCheck(index);
1043     checkForComodification();
1044     return l.get(index+offset);
1045     }
1046     }
1047    
1048     public int size() {
1049     synchronized(l) {
1050     checkForComodification();
1051     return size;
1052     }
1053     }
1054    
1055     public void add(int index, E element) {
1056     synchronized(l) {
1057     checkForComodification();
1058     if (index<0 || index>size)
1059     throw new IndexOutOfBoundsException();
1060     l.add(index+offset, element);
1061 dl 1.12 expectedArray = l.array;
1062 tim 1.1 size++;
1063     }
1064     }
1065    
1066 dl 1.13 public void clear() {
1067     synchronized(l) {
1068     checkForComodification();
1069     l.removeRange(offset, offset+size);
1070     expectedArray = l.array;
1071     size = 0;
1072     }
1073     }
1074    
1075 tim 1.1 public E remove(int index) {
1076     synchronized(l) {
1077     rangeCheck(index);
1078     checkForComodification();
1079     E result = l.remove(index+offset);
1080 dl 1.12 expectedArray = l.array;
1081 tim 1.1 size--;
1082     return result;
1083     }
1084     }
1085    
1086     public Iterator<E> iterator() {
1087     synchronized(l) {
1088     checkForComodification();
1089 tim 1.8 return new COWSubListIterator<E>(l, 0, offset, size);
1090 tim 1.1 }
1091     }
1092    
1093     public ListIterator<E> listIterator(final int index) {
1094     synchronized(l) {
1095     checkForComodification();
1096     if (index<0 || index>size)
1097     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
1098 tim 1.8 return new COWSubListIterator<E>(l, index, offset, size);
1099 tim 1.1 }
1100     }
1101    
1102 tim 1.7 public List<E> subList(int fromIndex, int toIndex) {
1103     synchronized(l) {
1104     checkForComodification();
1105     if (fromIndex<0 || toIndex>size)
1106     throw new IndexOutOfBoundsException();
1107     return new COWSubList<E>(l, fromIndex+offset, toIndex+offset);
1108 tim 1.1 }
1109 tim 1.7 }
1110 tim 1.1
1111 tim 1.7 }
1112 tim 1.1
1113    
1114 tim 1.7 private static class COWSubListIterator<E> implements ListIterator<E> {
1115     private final ListIterator<E> i;
1116     private final int index;
1117     private final int offset;
1118     private final int size;
1119     private COWSubListIterator(List<E> l, int index, int offset, int size) {
1120     this.index = index;
1121     this.offset = offset;
1122     this.size = size;
1123     i = l.listIterator(index+offset);
1124     }
1125 tim 1.1
1126 tim 1.7 public boolean hasNext() {
1127     return nextIndex() < size;
1128     }
1129 tim 1.1
1130 tim 1.7 public E next() {
1131     if (hasNext())
1132     return i.next();
1133     else
1134     throw new NoSuchElementException();
1135     }
1136 tim 1.1
1137 tim 1.7 public boolean hasPrevious() {
1138     return previousIndex() >= 0;
1139     }
1140 tim 1.1
1141 tim 1.7 public E previous() {
1142     if (hasPrevious())
1143     return i.previous();
1144     else
1145     throw new NoSuchElementException();
1146     }
1147 tim 1.1
1148 tim 1.7 public int nextIndex() {
1149     return i.nextIndex() - offset;
1150     }
1151 tim 1.1
1152 tim 1.7 public int previousIndex() {
1153     return i.previousIndex() - offset;
1154 tim 1.1 }
1155    
1156 tim 1.7 public void remove() {
1157     throw new UnsupportedOperationException();
1158     }
1159 tim 1.1
1160 tim 1.7 public void set(E o) {
1161     throw new UnsupportedOperationException();
1162 tim 1.1 }
1163    
1164 tim 1.7 public void add(E o) {
1165     throw new UnsupportedOperationException();
1166     }
1167 tim 1.1 }
1168    
1169     }