ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.39
Committed: Sun May 29 14:02:53 2005 UTC (19 years ago) by dl
Branch: MAIN
Changes since 1.38: +1 -5 lines
Log Message:
Avoid redundant bounds checks

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 dl 1.39 return array()[index];
363 tim 1.1 }
364    
365     /**
366 jsr166 1.35 * Replaces the element at the specified position in this list with the
367     * specified element.
368 tim 1.1 *
369 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
370 tim 1.1 */
371     public synchronized E set(int index, E element) {
372 dl 1.12 int len = array.length;
373     E oldValue = array[index];
374 tim 1.1
375     boolean same = (oldValue == element ||
376     (element != null && element.equals(oldValue)));
377     if (!same) {
378 tim 1.7 E[] newArray = (E[]) new Object[len];
379 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
380 tim 1.1 newArray[index] = element;
381 dl 1.12 array = newArray;
382 tim 1.1 }
383     return oldValue;
384     }
385    
386     /**
387     * Appends the specified element to the end of this list.
388     *
389 jsr166 1.35 * @param element element to be appended to this list
390     * @return <tt>true</tt> (as per the spec for {@link Collection#add})
391 tim 1.1 */
392     public synchronized boolean add(E element) {
393 dl 1.12 int len = array.length;
394 tim 1.7 E[] newArray = (E[]) new Object[len+1];
395 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
396 tim 1.1 newArray[len] = element;
397 dl 1.12 array = newArray;
398 tim 1.1 return true;
399     }
400    
401     /**
402     * Inserts the specified element at the specified position in this
403     * list. Shifts the element currently at that position (if any) and
404     * any subsequent elements to the right (adds one to their indices).
405     *
406 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
407 tim 1.1 */
408     public synchronized void add(int index, E element) {
409 dl 1.12 int len = array.length;
410 tim 1.1 if (index > len || index < 0)
411     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+len);
412    
413 tim 1.7 E[] newArray = (E[]) new Object[len+1];
414 dl 1.12 System.arraycopy(array, 0, newArray, 0, index);
415 tim 1.1 newArray[index] = element;
416 dl 1.12 System.arraycopy(array, index, newArray, index+1, len - index);
417     array = newArray;
418 tim 1.1 }
419    
420     /**
421     * Removes the element at the specified position in this list.
422     * Shifts any subsequent elements to the left (subtracts one from their
423 jsr166 1.35 * indices). Returns the element that was removed from the list.
424 tim 1.1 *
425 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
426 tim 1.1 */
427     public synchronized E remove(int index) {
428 dl 1.12 int len = array.length;
429     E oldValue = array[index];
430 tim 1.7 E[] newArray = (E[]) new Object[len-1];
431 dl 1.12 System.arraycopy(array, 0, newArray, 0, index);
432 tim 1.1 int numMoved = len - index - 1;
433     if (numMoved > 0)
434 dl 1.12 System.arraycopy(array, index+1, newArray, index, numMoved);
435     array = newArray;
436 tim 1.1 return oldValue;
437     }
438    
439     /**
440 jsr166 1.35 * Removes the first occurrence of the specified element from this list,
441     * if it is present. If this list does not contain the element, it is
442     * unchanged. More formally, removes the element with the lowest index
443     * <tt>i</tt> such that
444     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
445     * (if such an element exists). Returns <tt>true</tt> if this list
446     * contained the specified element (or equivalently, if this list
447     * changed as a result of the call).
448 tim 1.1 *
449 jsr166 1.35 * @param o element to be removed from this list, if present
450     * @return <tt>true</tt> if this list contained the specified element
451 tim 1.1 */
452 dl 1.15 public synchronized boolean remove(Object o) {
453 dl 1.12 int len = array.length;
454 tim 1.1 if (len == 0) return false;
455    
456     // Copy while searching for element to remove
457     // This wins in the normal case of element being present
458    
459     int newlen = len-1;
460 tim 1.7 E[] newArray = (E[]) new Object[newlen];
461 tim 1.1
462     for (int i = 0; i < newlen; ++i) {
463 dl 1.15 if (o == array[i] ||
464     (o != null && o.equals(array[i]))) {
465 tim 1.1 // found one; copy remaining and exit
466 dl 1.12 for (int k = i + 1; k < len; ++k) newArray[k-1] = array[k];
467     array = newArray;
468 tim 1.1 return true;
469 tim 1.10 } else
470 dl 1.12 newArray[i] = array[i];
471 tim 1.1 }
472     // special handling for last cell
473    
474 dl 1.15 if (o == array[newlen] ||
475     (o != null && o.equals(array[newlen]))) {
476 dl 1.12 array = newArray;
477 tim 1.1 return true;
478 tim 1.10 } else
479 tim 1.1 return false; // throw away copy
480     }
481    
482     /**
483 jsr166 1.35 * Removes from this list all of the elements whose index is between
484     * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
485     * Shifts any succeeding elements to the left (reduces their index).
486 dl 1.15 * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
487     * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
488 tim 1.1 *
489 jsr166 1.35 * @param fromIndex index of first element to be removed
490     * @param toIndex index after last element to be removed
491 dl 1.29 * @throws IndexOutOfBoundsException if fromIndex or toIndex out of
492 tim 1.1 * range (fromIndex &lt; 0 || fromIndex &gt;= size() || toIndex
493 jsr166 1.35 * &gt; size() || toIndex &lt; fromIndex)
494 tim 1.1 */
495     private synchronized void removeRange(int fromIndex, int toIndex) {
496 dl 1.12 int len = array.length;
497 tim 1.1
498     if (fromIndex < 0 || fromIndex >= len ||
499     toIndex > len || toIndex < fromIndex)
500     throw new IndexOutOfBoundsException();
501    
502     int numMoved = len - toIndex;
503     int newlen = len - (toIndex-fromIndex);
504 tim 1.7 E[] newArray = (E[]) new Object[newlen];
505 dl 1.12 System.arraycopy(array, 0, newArray, 0, fromIndex);
506     System.arraycopy(array, toIndex, newArray, fromIndex, numMoved);
507     array = newArray;
508 tim 1.1 }
509    
510     /**
511     * Append the element if not present.
512 jsr166 1.38 *
513 jsr166 1.35 * @param element element to be added to this list, if absent
514 jsr166 1.38 * @return <tt>true</tt> if the element was added
515 jsr166 1.30 */
516 tim 1.1 public synchronized boolean addIfAbsent(E element) {
517     // Copy while checking if already present.
518     // This wins in the most common case where it is not present
519 dl 1.12 int len = array.length;
520 tim 1.7 E[] newArray = (E[]) new Object[len + 1];
521 tim 1.1 for (int i = 0; i < len; ++i) {
522 dl 1.12 if (element == array[i] ||
523     (element != null && element.equals(array[i])))
524 tim 1.1 return false; // exit, throwing away copy
525     else
526 dl 1.12 newArray[i] = array[i];
527 tim 1.1 }
528     newArray[len] = element;
529 dl 1.12 array = newArray;
530 tim 1.1 return true;
531     }
532    
533     /**
534 jsr166 1.35 * Returns <tt>true</tt> if this list contains all of the elements of the
535 jsr166 1.32 * specified collection.
536 jsr166 1.34 *
537 jsr166 1.36 * @param c collection to be checked for containment in this list
538 jsr166 1.35 * @return <tt>true</tt> if this list contains all of the elements of the
539     * specified collection
540     * @throws NullPointerException if the specified collection is null
541 jsr166 1.38 * @see #contains(Object)
542 tim 1.1 */
543 tim 1.7 public boolean containsAll(Collection<?> c) {
544 tim 1.1 E[] elementData = array();
545     int len = elementData.length;
546 tim 1.7 Iterator e = c.iterator();
547 tim 1.1 while (e.hasNext())
548 dl 1.20 if (indexOf(e.next(), elementData, len) < 0)
549 tim 1.1 return false;
550    
551     return true;
552     }
553    
554     /**
555 jsr166 1.32 * Removes from this list all of its elements that are contained in
556     * the specified collection. This is a particularly expensive operation
557 tim 1.1 * in this class because of the need for an internal temporary array.
558     *
559 jsr166 1.35 * @param c collection containing elements to be removed from this list
560     * @return <tt>true</tt> if this list changed as a result of the call
561 jsr166 1.38 * @throws ClassCastException if the class of an element of this list
562     * is incompatible with the specified collection (optional)
563     * @throws NullPointerException if this list contains a null element and the
564     * specified collection does not permit null elements (optional),
565     * or if the specified collection is null
566     * @see #remove(Object)
567 tim 1.1 */
568 tim 1.7 public synchronized boolean removeAll(Collection<?> c) {
569 dl 1.12 E[] elementData = array;
570 tim 1.1 int len = elementData.length;
571     if (len == 0) return false;
572    
573     // temp array holds those elements we know we want to keep
574 tim 1.7 E[] temp = (E[]) new Object[len];
575 tim 1.1 int newlen = 0;
576     for (int i = 0; i < len; ++i) {
577     E element = elementData[i];
578     if (!c.contains(element)) {
579     temp[newlen++] = element;
580     }
581     }
582    
583     if (newlen == len) return false;
584    
585     // copy temp as new array
586 tim 1.7 E[] newArray = (E[]) new Object[newlen];
587 tim 1.1 System.arraycopy(temp, 0, newArray, 0, newlen);
588 dl 1.12 array = newArray;
589 tim 1.1 return true;
590     }
591    
592     /**
593 jsr166 1.32 * Retains only the elements in this list that are contained in the
594 jsr166 1.35 * specified collection. In other words, removes from this list all of
595     * its elements that are not contained in the specified collection.
596 jsr166 1.32 *
597 jsr166 1.35 * @param c collection containing elements to be retained in this list
598     * @return <tt>true</tt> if this list changed as a result of the call
599 jsr166 1.38 * @throws ClassCastException if the class of an element of this list
600     * is incompatible with the specified collection (optional)
601     * @throws NullPointerException if this list contains a null element and the
602     * specified collection does not permit null elements (optional),
603     * or if the specified collection is null
604     * @see #remove(Object)
605 tim 1.1 */
606 tim 1.7 public synchronized boolean retainAll(Collection<?> c) {
607 dl 1.12 E[] elementData = array;
608 tim 1.1 int len = elementData.length;
609     if (len == 0) return false;
610    
611 tim 1.7 E[] temp = (E[]) new Object[len];
612 tim 1.1 int newlen = 0;
613     for (int i = 0; i < len; ++i) {
614     E element = elementData[i];
615     if (c.contains(element)) {
616     temp[newlen++] = element;
617     }
618     }
619    
620     if (newlen == len) return false;
621    
622 tim 1.7 E[] newArray = (E[]) new Object[newlen];
623 tim 1.1 System.arraycopy(temp, 0, newArray, 0, newlen);
624 dl 1.12 array = newArray;
625 tim 1.1 return true;
626     }
627    
628     /**
629 jsr166 1.32 * Appends all of the elements in the specified collection that
630 tim 1.1 * are not already contained in this list, to the end of
631     * this list, in the order that they are returned by the
632 jsr166 1.32 * specified collection's iterator.
633 tim 1.1 *
634 jsr166 1.36 * @param c collection containing elements to be added to this list
635 tim 1.1 * @return the number of elements added
636 jsr166 1.35 * @throws NullPointerException if the specified collection is null
637 jsr166 1.38 * @see #addIfAbsent(Object)
638 tim 1.1 */
639 tim 1.7 public synchronized int addAllAbsent(Collection<? extends E> c) {
640 tim 1.1 int numNew = c.size();
641     if (numNew == 0) return 0;
642    
643 dl 1.12 E[] elementData = array;
644 tim 1.1 int len = elementData.length;
645    
646 tim 1.7 E[] temp = (E[]) new Object[numNew];
647 tim 1.1 int added = 0;
648 dl 1.20 Iterator<? extends E> e = c.iterator();
649 tim 1.1 while (e.hasNext()) {
650 dl 1.20 E element = e.next();
651 tim 1.1 if (indexOf(element, elementData, len) < 0) {
652     if (indexOf(element, temp, added) < 0) {
653     temp[added++] = element;
654     }
655     }
656     }
657    
658     if (added == 0) return 0;
659    
660 tim 1.7 E[] newArray = (E[]) new Object[len+added];
661 tim 1.1 System.arraycopy(elementData, 0, newArray, 0, len);
662     System.arraycopy(temp, 0, newArray, len, added);
663 dl 1.12 array = newArray;
664 tim 1.1 return added;
665     }
666    
667     /**
668     * Removes all of the elements from this list.
669 jsr166 1.38 * The list will be empty after this call returns.
670 tim 1.1 */
671     public synchronized void clear() {
672 dl 1.12 array = (E[]) new Object[0];
673 tim 1.1 }
674    
675     /**
676 jsr166 1.32 * Appends all of the elements in the specified collection to the end
677     * of this list, in the order that they are returned by the specified
678     * collection's iterator.
679 tim 1.1 *
680 jsr166 1.36 * @param c collection containing elements to be added to this list
681 jsr166 1.38 * @return <tt>true</tt> if this list changed as a result of the call
682 jsr166 1.35 * @throws NullPointerException if the specified collection is null
683 jsr166 1.38 * @see #add(Object)
684 tim 1.1 */
685 tim 1.7 public synchronized boolean addAll(Collection<? extends E> c) {
686 tim 1.1 int numNew = c.size();
687     if (numNew == 0) return false;
688    
689 dl 1.12 int len = array.length;
690 tim 1.7 E[] newArray = (E[]) new Object[len+numNew];
691 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
692 dl 1.20 Iterator<? extends E> e = c.iterator();
693 tim 1.1 for (int i=0; i<numNew; i++)
694 dl 1.20 newArray[len++] = e.next();
695 dl 1.12 array = newArray;
696 tim 1.1
697     return true;
698     }
699    
700     /**
701 jsr166 1.35 * Inserts all of the elements in the specified collection into this
702 tim 1.1 * list, starting at the specified position. Shifts the element
703     * currently at that position (if any) and any subsequent elements to
704     * the right (increases their indices). The new elements will appear
705 jsr166 1.38 * in this list in the order that they are returned by the
706     * specified collection's iterator.
707 tim 1.1 *
708 jsr166 1.35 * @param index index at which to insert the first element
709     * from the specified collection
710 jsr166 1.36 * @param c collection containing elements to be added to this list
711 jsr166 1.35 * @return <tt>true</tt> if this list changed as a result of the call
712     * @throws IndexOutOfBoundsException {@inheritDoc}
713     * @throws NullPointerException if the specified collection is null
714 jsr166 1.38 * @see #add(int,Object)
715 tim 1.1 */
716 tim 1.7 public synchronized boolean addAll(int index, Collection<? extends E> c) {
717 dl 1.12 int len = array.length;
718 tim 1.1 if (index > len || index < 0)
719     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+len);
720    
721     int numNew = c.size();
722     if (numNew == 0) return false;
723    
724 tim 1.7 E[] newArray = (E[]) new Object[len+numNew];
725 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
726 tim 1.1 int numMoved = len - index;
727     if (numMoved > 0)
728 dl 1.12 System.arraycopy(array, index, newArray, index + numNew, numMoved);
729 dl 1.20 Iterator<? extends E> e = c.iterator();
730 tim 1.1 for (int i=0; i<numNew; i++)
731 dl 1.20 newArray[index++] = e.next();
732 dl 1.12 array = newArray;
733 tim 1.1
734     return true;
735     }
736    
737     /**
738 jsr166 1.30 * Checks if the given index is in range. If not, throws an appropriate
739 tim 1.1 * runtime exception.
740     */
741     private void rangeCheck(int index, int length) {
742     if (index >= length || index < 0)
743     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+ length);
744     }
745    
746     /**
747     * Save the state of the list to a stream (i.e., serialize it).
748     *
749     * @serialData The length of the array backing the list is emitted
750     * (int), followed by all of its elements (each an Object)
751     * in the proper order.
752 dl 1.6 * @param s the stream
753 tim 1.1 */
754     private void writeObject(java.io.ObjectOutputStream s)
755     throws java.io.IOException{
756    
757     // Write out element count, and any hidden stuff
758     s.defaultWriteObject();
759    
760     E[] elementData = array();
761     // Write out array length
762     s.writeInt(elementData.length);
763    
764     // Write out all elements in the proper order.
765     for (int i=0; i<elementData.length; i++)
766     s.writeObject(elementData[i]);
767     }
768    
769     /**
770     * Reconstitute the list from a stream (i.e., deserialize it).
771 dl 1.6 * @param s the stream
772 tim 1.1 */
773 dl 1.12 private void readObject(java.io.ObjectInputStream s)
774 tim 1.1 throws java.io.IOException, ClassNotFoundException {
775    
776     // Read in size, and any hidden stuff
777     s.defaultReadObject();
778    
779     // Read in array length and allocate array
780     int arrayLength = s.readInt();
781 tim 1.7 E[] elementData = (E[]) new Object[arrayLength];
782 tim 1.1
783     // Read in all elements in the proper order.
784     for (int i=0; i<elementData.length; i++)
785     elementData[i] = (E) s.readObject();
786 dl 1.12 array = elementData;
787 tim 1.1 }
788    
789     /**
790 jsr166 1.32 * Returns a string representation of this list, containing
791 tim 1.1 * the String representation of each element.
792     */
793     public String toString() {
794     StringBuffer buf = new StringBuffer();
795     Iterator e = iterator();
796     buf.append("[");
797     int maxIndex = size() - 1;
798     for (int i = 0; i <= maxIndex; i++) {
799     buf.append(String.valueOf(e.next()));
800     if (i < maxIndex)
801     buf.append(", ");
802     }
803     buf.append("]");
804     return buf.toString();
805     }
806    
807     /**
808 jsr166 1.35 * Compares the specified object with this list for equality.
809     * Returns true if and only if the specified object is also a {@link
810     * List}, both lists have the same size, and all corresponding pairs
811     * of elements in the two lists are <em>equal</em>. (Two elements
812     * <tt>e1</tt> and <tt>e2</tt> are <em>equal</em> if <tt>(e1==null ?
813     * e2==null : e1.equals(e2))</tt>.) In other words, two lists are
814     * defined to be equal if they contain the same elements in the same
815     * order.
816 tim 1.1 *
817 jsr166 1.35 * @param o the object to be compared for equality with this list
818     * @return <tt>true</tt> if the specified object is equal to this list
819 tim 1.1 */
820     public boolean equals(Object o) {
821     if (o == this)
822     return true;
823     if (!(o instanceof List))
824     return false;
825    
826 tim 1.8 List<E> l2 = (List<E>)(o);
827 tim 1.1 if (size() != l2.size())
828     return false;
829    
830     ListIterator<E> e1 = listIterator();
831     ListIterator<E> e2 = l2.listIterator();
832 jsr166 1.35 while (e1.hasNext()) {
833 tim 1.1 E o1 = e1.next();
834     E o2 = e2.next();
835     if (!(o1==null ? o2==null : o1.equals(o2)))
836     return false;
837     }
838     return true;
839     }
840    
841     /**
842 jsr166 1.35 * Returns the hash code value for this list.
843 dl 1.26 *
844     * <p> This implementation uses the definition in {@link
845     * List#hashCode}.
846 dl 1.15 * @return the hash code
847 tim 1.1 */
848     public int hashCode() {
849     int hashCode = 1;
850     Iterator<E> i = iterator();
851     while (i.hasNext()) {
852     E obj = i.next();
853     hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
854     }
855     return hashCode;
856     }
857    
858     /**
859 jsr166 1.35 * Returns an iterator over the elements in this list in proper sequence.
860     *
861     * <p>The returned iterator provides a snapshot of the state of the list
862     * when the iterator was constructed. No synchronization is needed while
863     * traversing the iterator. The iterator does <em>NOT</em> support the
864     * <tt>remove</tt> method.
865     *
866     * @return an iterator over the elements in this list in proper sequence
867 tim 1.1 */
868     public Iterator<E> iterator() {
869     return new COWIterator<E>(array(), 0);
870     }
871    
872     /**
873 jsr166 1.35 * {@inheritDoc}
874 tim 1.1 *
875 jsr166 1.35 * <p>The returned iterator provides a snapshot of the state of the list
876     * when the iterator was constructed. No synchronization is needed while
877     * traversing the iterator. The iterator does <em>NOT</em> support the
878     * <tt>remove</tt>, <tt>set</tt> or <tt>add</tt> methods.
879 tim 1.1 */
880     public ListIterator<E> listIterator() {
881     return new COWIterator<E>(array(), 0);
882     }
883    
884     /**
885 jsr166 1.35 * {@inheritDoc}
886     *
887     * <p>The list iterator returned by this implementation will throw an
888     * <tt>UnsupportedOperationException</tt> in its <tt>remove</tt>,
889     * <tt>set</tt> and <tt>add</tt> methods.
890     *
891     * @throws IndexOutOfBoundsException {@inheritDoc}
892 tim 1.1 */
893     public ListIterator<E> listIterator(final int index) {
894     E[] elementData = array();
895     int len = elementData.length;
896     if (index<0 || index>len)
897     throw new IndexOutOfBoundsException("Index: "+index);
898    
899     return new COWIterator<E>(array(), index);
900     }
901    
902     private static class COWIterator<E> implements ListIterator<E> {
903    
904     /** Snapshot of the array **/
905     private final E[] array;
906    
907     /**
908     * Index of element to be returned by subsequent call to next.
909     */
910     private int cursor;
911    
912     private COWIterator(E[] elementArray, int initialCursor) {
913     array = elementArray;
914     cursor = initialCursor;
915     }
916    
917     public boolean hasNext() {
918     return cursor < array.length;
919     }
920    
921     public boolean hasPrevious() {
922     return cursor > 0;
923     }
924    
925     public E next() {
926     try {
927     return array[cursor++];
928 tim 1.10 } catch (IndexOutOfBoundsException ex) {
929 tim 1.1 throw new NoSuchElementException();
930     }
931     }
932    
933     public E previous() {
934     try {
935     return array[--cursor];
936 jsr166 1.30 } catch (IndexOutOfBoundsException e) {
937 tim 1.1 throw new NoSuchElementException();
938     }
939     }
940    
941     public int nextIndex() {
942     return cursor;
943     }
944    
945     public int previousIndex() {
946     return cursor-1;
947     }
948    
949     /**
950     * Not supported. Always throws UnsupportedOperationException.
951 jsr166 1.32 * @throws UnsupportedOperationException always; <tt>remove</tt>
952     * is not supported by this iterator.
953 tim 1.1 */
954     public void remove() {
955     throw new UnsupportedOperationException();
956     }
957    
958     /**
959     * Not supported. Always throws UnsupportedOperationException.
960 jsr166 1.32 * @throws UnsupportedOperationException always; <tt>set</tt>
961     * is not supported by this iterator.
962 tim 1.1 */
963 jsr166 1.33 public void set(E e) {
964 tim 1.1 throw new UnsupportedOperationException();
965     }
966    
967     /**
968     * Not supported. Always throws UnsupportedOperationException.
969 jsr166 1.32 * @throws UnsupportedOperationException always; <tt>add</tt>
970     * is not supported by this iterator.
971 tim 1.1 */
972 jsr166 1.33 public void add(E e) {
973 tim 1.1 throw new UnsupportedOperationException();
974     }
975     }
976    
977     /**
978 jsr166 1.35 * Returns a view of the portion of this list between <tt>fromIndex</tt>,
979     * inclusive, and <tt>toIndex</tt>, exclusive. The returned list is
980     * backed by this list, so changes in the returned list are reflected in
981     * this list, and vice-versa. While mutative operations are supported,
982     * they are probably not very useful for CopyOnWriteArrayLists.
983     *
984     * <p>The semantics of the list returned by this method become undefined if
985     * the backing list (i.e., this list) is <i>structurally modified</i> in
986     * any way other than via the returned list. (Structural modifications are
987     * those that change the size of the list, or otherwise perturb it in such
988 tim 1.1 * a fashion that iterations in progress may yield incorrect results.)
989     *
990 jsr166 1.35 * @param fromIndex low endpoint (inclusive) of the subList
991     * @param toIndex high endpoint (exclusive) of the subList
992     * @return a view of the specified range within this list
993     * @throws IndexOutOfBoundsException {@inheritDoc}
994 tim 1.1 */
995     public synchronized List<E> subList(int fromIndex, int toIndex) {
996 dl 1.21 // synchronized since sublist constructor depends on it.
997 dl 1.12 int len = array.length;
998 tim 1.1 if (fromIndex<0 || toIndex>len || fromIndex>toIndex)
999     throw new IndexOutOfBoundsException();
1000     return new COWSubList<E>(this, fromIndex, toIndex);
1001     }
1002    
1003     private static class COWSubList<E> extends AbstractList<E> {
1004    
1005     /*
1006 dl 1.2 This class extends AbstractList merely for convenience, to
1007     avoid having to define addAll, etc. This doesn't hurt, but
1008     is wasteful. This class does not need or use modCount
1009     mechanics in AbstractList, but does need to check for
1010     concurrent modification using similar mechanics. On each
1011     operation, the array that we expect the backing list to use
1012     is checked and updated. Since we do this for all of the
1013     base operations invoked by those defined in AbstractList,
1014     all is well. While inefficient, this is not worth
1015     improving. The kinds of list operations inherited from
1016 dl 1.20 AbstractList are already so slow on COW sublists that
1017 dl 1.2 adding a bit more space/time doesn't seem even noticeable.
1018 tim 1.1 */
1019    
1020     private final CopyOnWriteArrayList<E> l;
1021     private final int offset;
1022     private int size;
1023     private E[] expectedArray;
1024    
1025     private COWSubList(CopyOnWriteArrayList<E> list,
1026     int fromIndex, int toIndex) {
1027     l = list;
1028     expectedArray = l.array();
1029     offset = fromIndex;
1030     size = toIndex - fromIndex;
1031     }
1032    
1033     // only call this holding l's lock
1034     private void checkForComodification() {
1035 dl 1.12 if (l.array != expectedArray)
1036 tim 1.1 throw new ConcurrentModificationException();
1037     }
1038    
1039     // only call this holding l's lock
1040     private void rangeCheck(int index) {
1041     if (index<0 || index>=size)
1042     throw new IndexOutOfBoundsException("Index: "+index+ ",Size: "+size);
1043     }
1044    
1045    
1046     public E set(int index, E element) {
1047     synchronized(l) {
1048     rangeCheck(index);
1049     checkForComodification();
1050     E x = l.set(index+offset, element);
1051 dl 1.12 expectedArray = l.array;
1052 tim 1.1 return x;
1053     }
1054     }
1055    
1056     public E get(int index) {
1057     synchronized(l) {
1058     rangeCheck(index);
1059     checkForComodification();
1060     return l.get(index+offset);
1061     }
1062     }
1063    
1064     public int size() {
1065     synchronized(l) {
1066     checkForComodification();
1067     return size;
1068     }
1069     }
1070    
1071     public void add(int index, E element) {
1072     synchronized(l) {
1073     checkForComodification();
1074     if (index<0 || index>size)
1075     throw new IndexOutOfBoundsException();
1076     l.add(index+offset, element);
1077 dl 1.12 expectedArray = l.array;
1078 tim 1.1 size++;
1079     }
1080     }
1081    
1082 dl 1.13 public void clear() {
1083     synchronized(l) {
1084     checkForComodification();
1085     l.removeRange(offset, offset+size);
1086     expectedArray = l.array;
1087     size = 0;
1088     }
1089     }
1090    
1091 tim 1.1 public E remove(int index) {
1092     synchronized(l) {
1093     rangeCheck(index);
1094     checkForComodification();
1095     E result = l.remove(index+offset);
1096 dl 1.12 expectedArray = l.array;
1097 tim 1.1 size--;
1098     return result;
1099     }
1100     }
1101    
1102     public Iterator<E> iterator() {
1103     synchronized(l) {
1104     checkForComodification();
1105 tim 1.8 return new COWSubListIterator<E>(l, 0, offset, size);
1106 tim 1.1 }
1107     }
1108    
1109     public ListIterator<E> listIterator(final int index) {
1110     synchronized(l) {
1111     checkForComodification();
1112     if (index<0 || index>size)
1113     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
1114 tim 1.8 return new COWSubListIterator<E>(l, index, offset, size);
1115 tim 1.1 }
1116     }
1117    
1118 tim 1.7 public List<E> subList(int fromIndex, int toIndex) {
1119     synchronized(l) {
1120     checkForComodification();
1121     if (fromIndex<0 || toIndex>size)
1122     throw new IndexOutOfBoundsException();
1123     return new COWSubList<E>(l, fromIndex+offset, toIndex+offset);
1124 tim 1.1 }
1125 tim 1.7 }
1126 tim 1.1
1127 tim 1.7 }
1128 tim 1.1
1129    
1130 tim 1.7 private static class COWSubListIterator<E> implements ListIterator<E> {
1131     private final ListIterator<E> i;
1132     private final int index;
1133     private final int offset;
1134     private final int size;
1135     private COWSubListIterator(List<E> l, int index, int offset, int size) {
1136     this.index = index;
1137     this.offset = offset;
1138     this.size = size;
1139     i = l.listIterator(index+offset);
1140     }
1141 tim 1.1
1142 tim 1.7 public boolean hasNext() {
1143     return nextIndex() < size;
1144     }
1145 tim 1.1
1146 tim 1.7 public E next() {
1147     if (hasNext())
1148     return i.next();
1149     else
1150     throw new NoSuchElementException();
1151     }
1152 tim 1.1
1153 tim 1.7 public boolean hasPrevious() {
1154     return previousIndex() >= 0;
1155     }
1156 tim 1.1
1157 tim 1.7 public E previous() {
1158     if (hasPrevious())
1159     return i.previous();
1160     else
1161     throw new NoSuchElementException();
1162     }
1163 tim 1.1
1164 tim 1.7 public int nextIndex() {
1165     return i.nextIndex() - offset;
1166     }
1167 tim 1.1
1168 tim 1.7 public int previousIndex() {
1169     return i.previousIndex() - offset;
1170 tim 1.1 }
1171    
1172 tim 1.7 public void remove() {
1173     throw new UnsupportedOperationException();
1174     }
1175 tim 1.1
1176 jsr166 1.33 public void set(E e) {
1177 tim 1.7 throw new UnsupportedOperationException();
1178 tim 1.1 }
1179    
1180 jsr166 1.33 public void add(E e) {
1181 tim 1.7 throw new UnsupportedOperationException();
1182     }
1183 tim 1.1 }
1184    
1185     }