ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.23
Committed: Tue Jan 20 04:35:02 2004 UTC (20 years, 4 months ago) by dl
Branch: MAIN
Changes since 1.22: +3 -0 lines
Log Message:
javadoc lint; Thread.interrupt shouldn't throw exception if thread dead

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 dl 1.23 * @return the iterator
842 tim 1.1 */
843     public Iterator<E> iterator() {
844     return new COWIterator<E>(array(), 0);
845     }
846    
847     /**
848     * Returns an Iterator of the elements in this List (in proper sequence).
849     * The iterator provides a snapshot of the state of the list
850     * when the iterator was constructed. No synchronization is
851     * needed while traversing the iterator. The iterator does
852 dl 1.14 * <em>NOT</em> support the <tt>remove</tt>, <tt>set</tt>,
853     * or <tt>add</tt> methods.
854 dl 1.23 * @return the iterator
855 tim 1.1 *
856     */
857     public ListIterator<E> listIterator() {
858     return new COWIterator<E>(array(), 0);
859     }
860    
861     /**
862     * Returns a ListIterator of the elements in this List (in proper
863     * sequence), starting at the specified position in the List. The
864     * specified index indicates the first element that would be returned by
865     * an initial call to nextElement. An initial call to previousElement
866     * would return the element with the specified index minus one.
867     * The ListIterator returned by this implementation will throw
868     * an UnsupportedOperationException in its remove, set and
869     * add methods.
870     *
871     * @param index index of first element to be returned from the
872     * ListIterator (by a call to getNext).
873 dl 1.23 * @return the iterator
874 dl 1.6 * @throws IndexOutOfBoundsException index is out of range
875 tim 1.1 * (index &lt; 0 || index &gt; size()).
876     */
877     public ListIterator<E> listIterator(final int index) {
878     E[] elementData = array();
879     int len = elementData.length;
880     if (index<0 || index>len)
881     throw new IndexOutOfBoundsException("Index: "+index);
882    
883     return new COWIterator<E>(array(), index);
884     }
885    
886     private static class COWIterator<E> implements ListIterator<E> {
887    
888     /** Snapshot of the array **/
889     private final E[] array;
890    
891     /**
892     * Index of element to be returned by subsequent call to next.
893     */
894     private int cursor;
895    
896     private COWIterator(E[] elementArray, int initialCursor) {
897     array = elementArray;
898     cursor = initialCursor;
899     }
900    
901     public boolean hasNext() {
902     return cursor < array.length;
903     }
904    
905     public boolean hasPrevious() {
906     return cursor > 0;
907     }
908    
909     public E next() {
910     try {
911     return array[cursor++];
912 tim 1.10 } catch (IndexOutOfBoundsException ex) {
913 tim 1.1 throw new NoSuchElementException();
914     }
915     }
916    
917     public E previous() {
918     try {
919     return array[--cursor];
920     } catch(IndexOutOfBoundsException e) {
921     throw new NoSuchElementException();
922     }
923     }
924    
925     public int nextIndex() {
926     return cursor;
927     }
928    
929     public int previousIndex() {
930     return cursor-1;
931     }
932    
933     /**
934     * Not supported. Always throws UnsupportedOperationException.
935 dl 1.6 * @throws UnsupportedOperationException remove is not supported
936 tim 1.1 * by this Iterator.
937     */
938    
939     public void remove() {
940     throw new UnsupportedOperationException();
941     }
942    
943     /**
944     * Not supported. Always throws UnsupportedOperationException.
945 dl 1.6 * @throws UnsupportedOperationException set is not supported
946 tim 1.1 * by this Iterator.
947     */
948     public void set(E o) {
949     throw new UnsupportedOperationException();
950     }
951    
952     /**
953     * Not supported. Always throws UnsupportedOperationException.
954 dl 1.6 * @throws UnsupportedOperationException add is not supported
955 tim 1.1 * by this Iterator.
956     */
957     public void add(E o) {
958     throw new UnsupportedOperationException();
959     }
960     }
961    
962    
963     /**
964     * Returns a view of the portion of this List between fromIndex,
965     * inclusive, and toIndex, exclusive. The returned List is backed by this
966     * List, so changes in the returned List are reflected in this List, and
967     * vice-versa. While mutative operations are supported, they are
968 dl 1.16 * probably not very useful for CopyOnWriteArrayLists.
969 tim 1.9 * <p>
970 tim 1.1 * The semantics of the List returned by this method become undefined if
971     * the backing list (i.e., this List) is <i>structurally modified</i> in
972     * any way other than via the returned List. (Structural modifications are
973     * those that change the size of the List, or otherwise perturb it in such
974     * a fashion that iterations in progress may yield incorrect results.)
975     *
976     * @param fromIndex low endpoint (inclusive) of the subList.
977 dl 1.6 * @param toIndex high endpoint (exclusive) of the subList.
978 tim 1.1 * @return a view of the specified range within this List.
979 dl 1.6 * @throws IndexOutOfBoundsException Illegal endpoint index value
980 tim 1.1 * (fromIndex &lt; 0 || toIndex &gt; size || fromIndex &gt; toIndex).
981     */
982     public synchronized List<E> subList(int fromIndex, int toIndex) {
983 dl 1.21 // synchronized since sublist constructor depends on it.
984 dl 1.12 int len = array.length;
985 tim 1.1 if (fromIndex<0 || toIndex>len || fromIndex>toIndex)
986     throw new IndexOutOfBoundsException();
987     return new COWSubList<E>(this, fromIndex, toIndex);
988     }
989    
990     private static class COWSubList<E> extends AbstractList<E> {
991    
992     /*
993 dl 1.2 This class extends AbstractList merely for convenience, to
994     avoid having to define addAll, etc. This doesn't hurt, but
995     is wasteful. This class does not need or use modCount
996     mechanics in AbstractList, but does need to check for
997     concurrent modification using similar mechanics. On each
998     operation, the array that we expect the backing list to use
999     is checked and updated. Since we do this for all of the
1000     base operations invoked by those defined in AbstractList,
1001     all is well. While inefficient, this is not worth
1002     improving. The kinds of list operations inherited from
1003 dl 1.20 AbstractList are already so slow on COW sublists that
1004 dl 1.2 adding a bit more space/time doesn't seem even noticeable.
1005 tim 1.1 */
1006    
1007     private final CopyOnWriteArrayList<E> l;
1008     private final int offset;
1009     private int size;
1010     private E[] expectedArray;
1011    
1012     private COWSubList(CopyOnWriteArrayList<E> list,
1013     int fromIndex, int toIndex) {
1014     l = list;
1015     expectedArray = l.array();
1016     offset = fromIndex;
1017     size = toIndex - fromIndex;
1018     }
1019    
1020     // only call this holding l's lock
1021     private void checkForComodification() {
1022 dl 1.12 if (l.array != expectedArray)
1023 tim 1.1 throw new ConcurrentModificationException();
1024     }
1025    
1026     // only call this holding l's lock
1027     private void rangeCheck(int index) {
1028     if (index<0 || index>=size)
1029     throw new IndexOutOfBoundsException("Index: "+index+ ",Size: "+size);
1030     }
1031    
1032    
1033     public E set(int index, E element) {
1034     synchronized(l) {
1035     rangeCheck(index);
1036     checkForComodification();
1037     E x = l.set(index+offset, element);
1038 dl 1.12 expectedArray = l.array;
1039 tim 1.1 return x;
1040     }
1041     }
1042    
1043     public E get(int index) {
1044     synchronized(l) {
1045     rangeCheck(index);
1046     checkForComodification();
1047     return l.get(index+offset);
1048     }
1049     }
1050    
1051     public int size() {
1052     synchronized(l) {
1053     checkForComodification();
1054     return size;
1055     }
1056     }
1057    
1058     public void add(int index, E element) {
1059     synchronized(l) {
1060     checkForComodification();
1061     if (index<0 || index>size)
1062     throw new IndexOutOfBoundsException();
1063     l.add(index+offset, element);
1064 dl 1.12 expectedArray = l.array;
1065 tim 1.1 size++;
1066     }
1067     }
1068    
1069 dl 1.13 public void clear() {
1070     synchronized(l) {
1071     checkForComodification();
1072     l.removeRange(offset, offset+size);
1073     expectedArray = l.array;
1074     size = 0;
1075     }
1076     }
1077    
1078 tim 1.1 public E remove(int index) {
1079     synchronized(l) {
1080     rangeCheck(index);
1081     checkForComodification();
1082     E result = l.remove(index+offset);
1083 dl 1.12 expectedArray = l.array;
1084 tim 1.1 size--;
1085     return result;
1086     }
1087     }
1088    
1089     public Iterator<E> iterator() {
1090     synchronized(l) {
1091     checkForComodification();
1092 tim 1.8 return new COWSubListIterator<E>(l, 0, offset, size);
1093 tim 1.1 }
1094     }
1095    
1096     public ListIterator<E> listIterator(final int index) {
1097     synchronized(l) {
1098     checkForComodification();
1099     if (index<0 || index>size)
1100     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
1101 tim 1.8 return new COWSubListIterator<E>(l, index, offset, size);
1102 tim 1.1 }
1103     }
1104    
1105 tim 1.7 public List<E> subList(int fromIndex, int toIndex) {
1106     synchronized(l) {
1107     checkForComodification();
1108     if (fromIndex<0 || toIndex>size)
1109     throw new IndexOutOfBoundsException();
1110     return new COWSubList<E>(l, fromIndex+offset, toIndex+offset);
1111 tim 1.1 }
1112 tim 1.7 }
1113 tim 1.1
1114 tim 1.7 }
1115 tim 1.1
1116    
1117 tim 1.7 private static class COWSubListIterator<E> implements ListIterator<E> {
1118     private final ListIterator<E> i;
1119     private final int index;
1120     private final int offset;
1121     private final int size;
1122     private COWSubListIterator(List<E> l, int index, int offset, int size) {
1123     this.index = index;
1124     this.offset = offset;
1125     this.size = size;
1126     i = l.listIterator(index+offset);
1127     }
1128 tim 1.1
1129 tim 1.7 public boolean hasNext() {
1130     return nextIndex() < size;
1131     }
1132 tim 1.1
1133 tim 1.7 public E next() {
1134     if (hasNext())
1135     return i.next();
1136     else
1137     throw new NoSuchElementException();
1138     }
1139 tim 1.1
1140 tim 1.7 public boolean hasPrevious() {
1141     return previousIndex() >= 0;
1142     }
1143 tim 1.1
1144 tim 1.7 public E previous() {
1145     if (hasPrevious())
1146     return i.previous();
1147     else
1148     throw new NoSuchElementException();
1149     }
1150 tim 1.1
1151 tim 1.7 public int nextIndex() {
1152     return i.nextIndex() - offset;
1153     }
1154 tim 1.1
1155 tim 1.7 public int previousIndex() {
1156     return i.previousIndex() - offset;
1157 tim 1.1 }
1158    
1159 tim 1.7 public void remove() {
1160     throw new UnsupportedOperationException();
1161     }
1162 tim 1.1
1163 tim 1.7 public void set(E o) {
1164     throw new UnsupportedOperationException();
1165 tim 1.1 }
1166    
1167 tim 1.7 public void add(E o) {
1168     throw new UnsupportedOperationException();
1169     }
1170 tim 1.1 }
1171    
1172     }