ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.37
Committed: Sat May 21 03:02:42 2005 UTC (19 years ago) by jsr166
Branch: MAIN
Changes since 1.36: +0 -5 lines
Log Message:
containsAll

File Contents

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