ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.38
Committed: Sat May 21 17:32:20 2005 UTC (19 years ago) by jsr166
Branch: MAIN
Changes since 1.37: +23 -9 lines
Log Message:
doc fixes

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