ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.41
Committed: Tue May 31 17:39:18 2005 UTC (19 years ago) by dl
Branch: MAIN
Changes since 1.40: +110 -116 lines
Log Message:
Reduce generics warnings

File Contents

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