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