ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.40
Committed: Tue May 31 13:56:31 2005 UTC (19 years ago) by dl
Branch: MAIN
Changes since 1.39: +352 -337 lines
Log Message:
Use anticipated Arrays.clone methods

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