ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.112
Committed: Thu Jul 18 18:21:22 2013 UTC (10 years, 10 months ago) by jsr166
Branch: MAIN
Changes since 1.111: +4 -0 lines
Log Message:
javadoc warning fixes: add serialization method @throws

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 dl 1.98 import java.util.AbstractList;
19 dl 1.93 import java.util.Arrays;
20     import java.util.Collection;
21 dl 1.98 import java.util.Collections;
22 dl 1.106 import java.util.Comparator;
23 dl 1.98 import java.util.ConcurrentModificationException;
24     import java.util.Iterator;
25 dl 1.93 import java.util.List;
26     import java.util.ListIterator;
27 dl 1.98 import java.util.NoSuchElementException;
28 dl 1.93 import java.util.RandomAccess;
29     import java.util.Spliterator;
30 dl 1.99 import java.util.Spliterators;
31 dl 1.98 import java.util.concurrent.locks.ReentrantLock;
32     import java.util.function.Consumer;
33 dl 1.106 import java.util.function.Predicate;
34     import java.util.function.UnaryOperator;
35 tim 1.1
36     /**
37 dl 1.28 * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
38 jsr166 1.92 * operations ({@code add}, {@code set}, and so on) are implemented by
39 jsr166 1.35 * making a fresh copy of the underlying array.
40 tim 1.1 *
41 jsr166 1.91 * <p>This is ordinarily too costly, but may be <em>more</em> efficient
42 dl 1.12 * than alternatives when traversal operations vastly outnumber
43     * mutations, and is useful when you cannot or don't want to
44     * synchronize traversals, yet need to preclude interference among
45 dl 1.15 * concurrent threads. The "snapshot" style iterator method uses a
46     * reference to the state of the array at the point that the iterator
47     * was created. This array never changes during the lifetime of the
48     * iterator, so interference is impossible and the iterator is
49 jsr166 1.92 * guaranteed not to throw {@code ConcurrentModificationException}.
50 dl 1.15 * The iterator will not reflect additions, removals, or changes to
51     * the list since the iterator was created. Element-changing
52 jsr166 1.92 * operations on iterators themselves ({@code remove}, {@code set}, and
53     * {@code add}) are not supported. These methods throw
54     * {@code UnsupportedOperationException}.
55 dl 1.24 *
56 jsr166 1.92 * <p>All elements are permitted, including {@code null}.
57 jsr166 1.35 *
58 jsr166 1.56 * <p>Memory consistency effects: As with other concurrent
59     * collections, actions in a thread prior to placing an object into a
60     * {@code CopyOnWriteArrayList}
61     * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
62     * actions subsequent to the access or removal of that element from
63     * the {@code CopyOnWriteArrayList} in another thread.
64     *
65 dl 1.24 * <p>This class is a member of the
66 jsr166 1.64 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
67 dl 1.24 * Java Collections Framework</a>.
68     *
69 dl 1.6 * @since 1.5
70     * @author Doug Lea
71 dl 1.19 * @param <E> the type of elements held in this collection
72 dl 1.6 */
73 tim 1.1 public class CopyOnWriteArrayList<E>
74 dl 1.40 implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
75 dl 1.11 private static final long serialVersionUID = 8673264195747942595L;
76 tim 1.1
77 dl 1.42 /** The lock protecting all mutators */
78 jsr166 1.95 final transient ReentrantLock lock = new ReentrantLock();
79 dl 1.42
80 dl 1.40 /** The array, accessed only via getArray/setArray. */
81 jsr166 1.95 private transient volatile Object[] array;
82 tim 1.1
83 dl 1.57 /**
84 jsr166 1.60 * Gets the array. Non-private so as to also be accessible
85     * from CopyOnWriteArraySet class.
86 dl 1.57 */
87 jsr166 1.63 final Object[] getArray() {
88 jsr166 1.59 return array;
89 dl 1.57 }
90    
91     /**
92 jsr166 1.60 * Sets the array.
93 dl 1.57 */
94 jsr166 1.59 final void setArray(Object[] a) {
95     array = a;
96 dl 1.57 }
97 tim 1.1
98     /**
99 dl 1.15 * Creates an empty list.
100 tim 1.1 */
101     public CopyOnWriteArrayList() {
102 dl 1.41 setArray(new Object[0]);
103 tim 1.1 }
104    
105     /**
106 dl 1.15 * Creates a list containing the elements of the specified
107 jsr166 1.32 * collection, in the order they are returned by the collection's
108 tim 1.1 * iterator.
109 jsr166 1.32 *
110 dl 1.6 * @param c the collection of initially held elements
111 jsr166 1.35 * @throws NullPointerException if the specified collection is null
112 tim 1.1 */
113 tim 1.22 public CopyOnWriteArrayList(Collection<? extends E> c) {
114 dl 1.106 Object[] elements;
115     if (c.getClass() == CopyOnWriteArrayList.class)
116     elements = ((CopyOnWriteArrayList<?>)c).getArray();
117     else {
118     elements = c.toArray();
119     // c.toArray might (incorrectly) not return Object[] (see 6260652)
120     if (elements.getClass() != Object[].class)
121     elements = Arrays.copyOf(elements, elements.length, Object[].class);
122     }
123 jsr166 1.67 setArray(elements);
124 tim 1.1 }
125    
126     /**
127 jsr166 1.35 * Creates a list holding a copy of the given array.
128 tim 1.9 *
129     * @param toCopyIn the array (a copy of this array is used as the
130     * internal array)
131 jsr166 1.38 * @throws NullPointerException if the specified array is null
132 jsr166 1.30 */
133 tim 1.1 public CopyOnWriteArrayList(E[] toCopyIn) {
134 jsr166 1.67 setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
135 tim 1.1 }
136    
137     /**
138 dl 1.15 * Returns the number of elements in this list.
139 tim 1.1 *
140 jsr166 1.35 * @return the number of elements in this list
141 tim 1.1 */
142     public int size() {
143 dl 1.40 return getArray().length;
144 tim 1.1 }
145    
146     /**
147 jsr166 1.92 * Returns {@code true} if this list contains no elements.
148 tim 1.1 *
149 jsr166 1.92 * @return {@code true} if this list contains no elements
150 tim 1.1 */
151     public boolean isEmpty() {
152     return size() == 0;
153     }
154    
155 dl 1.43 /**
156 jsr166 1.90 * Tests for equality, coping with nulls.
157 dl 1.43 */
158     private static boolean eq(Object o1, Object o2) {
159 jsr166 1.102 return (o1 == null) ? o2 == null : o1.equals(o2);
160 dl 1.43 }
161    
162 dl 1.41 /**
163 dl 1.40 * static version of indexOf, to allow repeated calls without
164 dl 1.41 * needing to re-acquire array each time.
165 dl 1.40 * @param o element to search for
166     * @param elements the array
167     * @param index first index to search
168     * @param fence one past last index to search
169     * @return index of element, or -1 if absent
170     */
171 dl 1.41 private static int indexOf(Object o, Object[] elements,
172 dl 1.40 int index, int fence) {
173     if (o == null) {
174     for (int i = index; i < fence; i++)
175     if (elements[i] == null)
176     return i;
177     } else {
178     for (int i = index; i < fence; i++)
179     if (o.equals(elements[i]))
180     return i;
181     }
182     return -1;
183     }
184 dl 1.41
185     /**
186 dl 1.40 * static version of lastIndexOf.
187     * @param o element to search for
188     * @param elements the array
189     * @param index first index to search
190     * @return index of element, or -1 if absent
191     */
192     private static int lastIndexOf(Object o, Object[] elements, int index) {
193     if (o == null) {
194     for (int i = index; i >= 0; i--)
195     if (elements[i] == null)
196     return i;
197     } else {
198     for (int i = index; i >= 0; i--)
199     if (o.equals(elements[i]))
200     return i;
201     }
202     return -1;
203     }
204    
205 tim 1.1 /**
206 jsr166 1.92 * Returns {@code true} if this list contains the specified element.
207     * More formally, returns {@code true} if and only if this list contains
208     * at least one element {@code e} such that
209 jsr166 1.35 * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
210 tim 1.1 *
211 jsr166 1.35 * @param o element whose presence in this list is to be tested
212 jsr166 1.92 * @return {@code true} if this list contains the specified element
213 tim 1.1 */
214 jsr166 1.35 public boolean contains(Object o) {
215 dl 1.41 Object[] elements = getArray();
216 dl 1.40 return indexOf(o, elements, 0, elements.length) >= 0;
217 tim 1.1 }
218    
219     /**
220 jsr166 1.35 * {@inheritDoc}
221 tim 1.1 */
222 jsr166 1.35 public int indexOf(Object o) {
223 dl 1.41 Object[] elements = getArray();
224 dl 1.40 return indexOf(o, elements, 0, elements.length);
225 tim 1.1 }
226    
227     /**
228 jsr166 1.35 * Returns the index of the first occurrence of the specified element in
229 jsr166 1.92 * this list, searching forwards from {@code index}, or returns -1 if
230 jsr166 1.35 * the element is not found.
231 jsr166 1.92 * More formally, returns the lowest index {@code i} such that
232 jsr166 1.35 * <tt>(i&nbsp;&gt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(e==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;e.equals(get(i))))</tt>,
233     * or -1 if there is no such index.
234     *
235     * @param e element to search for
236     * @param index index to start searching from
237     * @return the index of the first occurrence of the element in
238 jsr166 1.92 * this list at position {@code index} or later in the list;
239     * {@code -1} if the element is not found.
240 jsr166 1.35 * @throws IndexOutOfBoundsException if the specified index is negative
241 tim 1.1 */
242 jsr166 1.35 public int indexOf(E e, int index) {
243 dl 1.41 Object[] elements = getArray();
244 jsr166 1.67 return indexOf(e, elements, index, elements.length);
245 tim 1.1 }
246    
247     /**
248 jsr166 1.35 * {@inheritDoc}
249 tim 1.1 */
250 jsr166 1.35 public int lastIndexOf(Object o) {
251 dl 1.41 Object[] elements = getArray();
252 dl 1.40 return lastIndexOf(o, elements, elements.length - 1);
253 tim 1.1 }
254    
255     /**
256 jsr166 1.35 * Returns the index of the last occurrence of the specified element in
257 jsr166 1.92 * this list, searching backwards from {@code index}, or returns -1 if
258 jsr166 1.35 * the element is not found.
259 jsr166 1.92 * More formally, returns the highest index {@code i} such that
260 jsr166 1.35 * <tt>(i&nbsp;&lt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(e==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;e.equals(get(i))))</tt>,
261     * or -1 if there is no such index.
262     *
263     * @param e element to search for
264     * @param index index to start searching backwards from
265     * @return the index of the last occurrence of the element at position
266 jsr166 1.92 * less than or equal to {@code index} in this list;
267 jsr166 1.35 * -1 if the element is not found.
268     * @throws IndexOutOfBoundsException if the specified index is greater
269     * than or equal to the current size of this list
270 tim 1.1 */
271 jsr166 1.35 public int lastIndexOf(E e, int index) {
272 dl 1.41 Object[] elements = getArray();
273 jsr166 1.67 return lastIndexOf(e, elements, index);
274 tim 1.1 }
275    
276     /**
277     * Returns a shallow copy of this list. (The elements themselves
278     * are not copied.)
279     *
280 jsr166 1.35 * @return a clone of this list
281 tim 1.1 */
282     public Object clone() {
283     try {
284 jsr166 1.83 @SuppressWarnings("unchecked")
285     CopyOnWriteArrayList<E> clone =
286     (CopyOnWriteArrayList<E>) super.clone();
287     clone.resetLock();
288     return clone;
289 tim 1.1 } catch (CloneNotSupportedException e) {
290     // this shouldn't happen, since we are Cloneable
291     throw new InternalError();
292     }
293     }
294    
295     /**
296     * Returns an array containing all of the elements in this list
297 jsr166 1.35 * in proper sequence (from first to last element).
298     *
299     * <p>The returned array will be "safe" in that no references to it are
300     * maintained by this list. (In other words, this method must allocate
301     * a new array). The caller is thus free to modify the returned array.
302 jsr166 1.36 *
303 jsr166 1.35 * <p>This method acts as bridge between array-based and collection-based
304     * APIs.
305     *
306     * @return an array containing all the elements in this list
307 tim 1.1 */
308     public Object[] toArray() {
309 dl 1.40 Object[] elements = getArray();
310 jsr166 1.67 return Arrays.copyOf(elements, elements.length);
311 tim 1.1 }
312    
313     /**
314 jsr166 1.35 * Returns an array containing all of the elements in this list in
315     * proper sequence (from first to last element); the runtime type of
316     * the returned array is that of the specified array. If the list fits
317     * in the specified array, it is returned therein. Otherwise, a new
318     * array is allocated with the runtime type of the specified array and
319     * the size of this list.
320 jsr166 1.32 *
321     * <p>If this list fits in the specified array with room to spare
322 jsr166 1.35 * (i.e., the array has more elements than this list), the element in
323     * the array immediately following the end of the list is set to
324 jsr166 1.92 * {@code null}. (This is useful in determining the length of this
325 jsr166 1.35 * list <i>only</i> if the caller knows that this list does not contain
326     * any null elements.)
327     *
328     * <p>Like the {@link #toArray()} method, this method acts as bridge between
329     * array-based and collection-based APIs. Further, this method allows
330     * precise control over the runtime type of the output array, and may,
331     * under certain circumstances, be used to save allocation costs.
332     *
333 jsr166 1.92 * <p>Suppose {@code x} is a list known to contain only strings.
334 jsr166 1.35 * The following code can be used to dump the list into a newly
335 jsr166 1.92 * allocated array of {@code String}:
336 jsr166 1.35 *
337 jsr166 1.81 * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
338 jsr166 1.35 *
339 jsr166 1.92 * Note that {@code toArray(new Object[0])} is identical in function to
340     * {@code toArray()}.
341 tim 1.1 *
342     * @param a the array into which the elements of the list are to
343 jsr166 1.35 * be stored, if it is big enough; otherwise, a new array of the
344     * same runtime type is allocated for this purpose.
345     * @return an array containing all the elements in this list
346     * @throws ArrayStoreException if the runtime type of the specified array
347     * is not a supertype of the runtime type of every element in
348     * this list
349     * @throws NullPointerException if the specified array is null
350 tim 1.1 */
351 jsr166 1.66 @SuppressWarnings("unchecked")
352 tim 1.1 public <T> T[] toArray(T a[]) {
353 dl 1.41 Object[] elements = getArray();
354 dl 1.40 int len = elements.length;
355     if (a.length < len)
356 jsr166 1.67 return (T[]) Arrays.copyOf(elements, len, a.getClass());
357     else {
358     System.arraycopy(elements, 0, a, 0, len);
359     if (a.length > len)
360     a[len] = null;
361     return a;
362     }
363 tim 1.1 }
364    
365     // Positional Access Operations
366    
367 jsr166 1.66 @SuppressWarnings("unchecked")
368     private E get(Object[] a, int index) {
369 jsr166 1.67 return (E) a[index];
370 jsr166 1.66 }
371    
372 tim 1.1 /**
373 jsr166 1.35 * {@inheritDoc}
374 tim 1.1 *
375 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
376 tim 1.1 */
377     public E get(int index) {
378 jsr166 1.66 return get(getArray(), index);
379 tim 1.1 }
380    
381     /**
382 jsr166 1.35 * Replaces the element at the specified position in this list with the
383     * specified element.
384 tim 1.1 *
385 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
386 tim 1.1 */
387 dl 1.42 public E set(int index, E element) {
388 jsr166 1.67 final ReentrantLock lock = this.lock;
389     lock.lock();
390     try {
391     Object[] elements = getArray();
392     E oldValue = get(elements, index);
393    
394     if (oldValue != element) {
395     int len = elements.length;
396     Object[] newElements = Arrays.copyOf(elements, len);
397     newElements[index] = element;
398     setArray(newElements);
399     } else {
400     // Not quite a no-op; ensures volatile write semantics
401     setArray(elements);
402     }
403     return oldValue;
404     } finally {
405     lock.unlock();
406     }
407 tim 1.1 }
408    
409     /**
410     * Appends the specified element to the end of this list.
411     *
412 dl 1.40 * @param e element to be appended to this list
413 jsr166 1.92 * @return {@code true} (as specified by {@link Collection#add})
414 tim 1.1 */
415 dl 1.42 public boolean add(E e) {
416 jsr166 1.67 final ReentrantLock lock = this.lock;
417     lock.lock();
418     try {
419     Object[] elements = getArray();
420     int len = elements.length;
421     Object[] newElements = Arrays.copyOf(elements, len + 1);
422     newElements[len] = e;
423     setArray(newElements);
424     return true;
425     } finally {
426     lock.unlock();
427     }
428 tim 1.1 }
429    
430     /**
431     * Inserts the specified element at the specified position in this
432     * list. Shifts the element currently at that position (if any) and
433     * any subsequent elements to the right (adds one to their indices).
434     *
435 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
436 tim 1.1 */
437 dl 1.42 public void add(int index, E element) {
438 jsr166 1.67 final ReentrantLock lock = this.lock;
439     lock.lock();
440     try {
441     Object[] elements = getArray();
442     int len = elements.length;
443     if (index > len || index < 0)
444     throw new IndexOutOfBoundsException("Index: "+index+
445     ", Size: "+len);
446     Object[] newElements;
447     int numMoved = len - index;
448     if (numMoved == 0)
449     newElements = Arrays.copyOf(elements, len + 1);
450     else {
451     newElements = new Object[len + 1];
452     System.arraycopy(elements, 0, newElements, 0, index);
453     System.arraycopy(elements, index, newElements, index + 1,
454     numMoved);
455     }
456     newElements[index] = element;
457     setArray(newElements);
458     } finally {
459     lock.unlock();
460     }
461 tim 1.1 }
462    
463     /**
464     * Removes the element at the specified position in this list.
465     * Shifts any subsequent elements to the left (subtracts one from their
466 jsr166 1.35 * indices). Returns the element that was removed from the list.
467 tim 1.1 *
468 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
469 tim 1.1 */
470 dl 1.42 public E remove(int index) {
471 jsr166 1.67 final ReentrantLock lock = this.lock;
472     lock.lock();
473     try {
474     Object[] elements = getArray();
475     int len = elements.length;
476     E oldValue = get(elements, index);
477     int numMoved = len - index - 1;
478     if (numMoved == 0)
479     setArray(Arrays.copyOf(elements, len - 1));
480     else {
481     Object[] newElements = new Object[len - 1];
482     System.arraycopy(elements, 0, newElements, 0, index);
483     System.arraycopy(elements, index + 1, newElements, index,
484     numMoved);
485     setArray(newElements);
486     }
487     return oldValue;
488     } finally {
489     lock.unlock();
490     }
491 tim 1.1 }
492    
493     /**
494 jsr166 1.35 * Removes the first occurrence of the specified element from this list,
495     * if it is present. If this list does not contain the element, it is
496     * unchanged. More formally, removes the element with the lowest index
497 jsr166 1.92 * {@code i} such that
498 jsr166 1.35 * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
499 jsr166 1.92 * (if such an element exists). Returns {@code true} if this list
500 jsr166 1.35 * contained the specified element (or equivalently, if this list
501     * changed as a result of the call).
502 tim 1.1 *
503 jsr166 1.35 * @param o element to be removed from this list, if present
504 jsr166 1.92 * @return {@code true} if this list contained the specified element
505 tim 1.1 */
506 dl 1.42 public boolean remove(Object o) {
507 jsr166 1.104 Object[] snapshot = getArray();
508     int index = indexOf(o, snapshot, 0, snapshot.length);
509     return (index < 0) ? false : remove(o, snapshot, index);
510     }
511    
512     /**
513     * A version of remove(Object) using the strong hint that given
514     * recent snapshot contains o at the given index.
515     */
516     private boolean remove(Object o, Object[] snapshot, int index) {
517 jsr166 1.67 final ReentrantLock lock = this.lock;
518     lock.lock();
519     try {
520 jsr166 1.104 Object[] current = getArray();
521     int len = current.length;
522     if (snapshot != current) findIndex: {
523     int prefix = Math.min(index, len);
524     for (int i = 0; i < prefix; i++) {
525     if (current[i] != snapshot[i] && eq(o, current[i])) {
526     index = i;
527     break findIndex;
528     }
529 jsr166 1.67 }
530 jsr166 1.104 if (index >= len)
531     return false;
532     if (current[index] == o)
533     break findIndex;
534     index = indexOf(o, current, index, len);
535     if (index < 0)
536     return false;
537 jsr166 1.67 }
538 jsr166 1.104 Object[] newElements = new Object[len - 1];
539     System.arraycopy(current, 0, newElements, 0, index);
540     System.arraycopy(current, index + 1,
541     newElements, index,
542     len - index - 1);
543     setArray(newElements);
544     return true;
545 jsr166 1.67 } finally {
546     lock.unlock();
547     }
548 tim 1.1 }
549    
550     /**
551 jsr166 1.35 * Removes from this list all of the elements whose index is between
552 jsr166 1.92 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
553 jsr166 1.35 * Shifts any succeeding elements to the left (reduces their index).
554 jsr166 1.92 * This call shortens the list by {@code (toIndex - fromIndex)} elements.
555     * (If {@code toIndex==fromIndex}, this operation has no effect.)
556 tim 1.1 *
557 jsr166 1.35 * @param fromIndex index of first element to be removed
558     * @param toIndex index after last element to be removed
559 jsr166 1.66 * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range
560 jsr166 1.86 * ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
561 tim 1.1 */
562 jsr166 1.84 void removeRange(int fromIndex, int toIndex) {
563 jsr166 1.67 final ReentrantLock lock = this.lock;
564     lock.lock();
565     try {
566     Object[] elements = getArray();
567     int len = elements.length;
568    
569     if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
570     throw new IndexOutOfBoundsException();
571     int newlen = len - (toIndex - fromIndex);
572     int numMoved = len - toIndex;
573     if (numMoved == 0)
574     setArray(Arrays.copyOf(elements, newlen));
575     else {
576     Object[] newElements = new Object[newlen];
577     System.arraycopy(elements, 0, newElements, 0, fromIndex);
578     System.arraycopy(elements, toIndex, newElements,
579     fromIndex, numMoved);
580     setArray(newElements);
581     }
582     } finally {
583     lock.unlock();
584     }
585 tim 1.1 }
586    
587     /**
588 jsr166 1.90 * Appends the element, if not present.
589 jsr166 1.38 *
590 dl 1.40 * @param e element to be added to this list, if absent
591 jsr166 1.92 * @return {@code true} if the element was added
592 jsr166 1.30 */
593 dl 1.42 public boolean addIfAbsent(E e) {
594 jsr166 1.104 Object[] snapshot = getArray();
595     return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
596     addIfAbsent(e, snapshot);
597     }
598    
599     /**
600     * A version of addIfAbsent using the strong hint that given
601     * recent snapshot does not contain e.
602     */
603     private boolean addIfAbsent(E e, Object[] snapshot) {
604 jsr166 1.67 final ReentrantLock lock = this.lock;
605     lock.lock();
606     try {
607 jsr166 1.104 Object[] current = getArray();
608     int len = current.length;
609     if (snapshot != current) {
610     // Optimize for lost race to another addXXX operation
611     int common = Math.min(snapshot.length, len);
612     for (int i = 0; i < common; i++)
613     if (current[i] != snapshot[i] && eq(e, current[i]))
614     return false;
615     if (indexOf(e, current, common, len) >= 0)
616     return false;
617 jsr166 1.67 }
618 jsr166 1.104 Object[] newElements = Arrays.copyOf(current, len + 1);
619 jsr166 1.67 newElements[len] = e;
620     setArray(newElements);
621     return true;
622     } finally {
623     lock.unlock();
624     }
625 tim 1.1 }
626    
627     /**
628 jsr166 1.92 * Returns {@code true} if this list contains all of the elements of the
629 jsr166 1.32 * specified collection.
630 jsr166 1.34 *
631 jsr166 1.36 * @param c collection to be checked for containment in this list
632 jsr166 1.92 * @return {@code true} if this list contains all of the elements of the
633 jsr166 1.35 * specified collection
634     * @throws NullPointerException if the specified collection is null
635 jsr166 1.38 * @see #contains(Object)
636 tim 1.1 */
637 tim 1.7 public boolean containsAll(Collection<?> c) {
638 dl 1.41 Object[] elements = getArray();
639 dl 1.40 int len = elements.length;
640 jsr166 1.67 for (Object e : c) {
641 dl 1.41 if (indexOf(e, elements, 0, len) < 0)
642 tim 1.1 return false;
643 jsr166 1.67 }
644 tim 1.1 return true;
645     }
646    
647     /**
648 jsr166 1.32 * Removes from this list all of its elements that are contained in
649     * the specified collection. This is a particularly expensive operation
650 tim 1.1 * in this class because of the need for an internal temporary array.
651     *
652 jsr166 1.35 * @param c collection containing elements to be removed from this list
653 jsr166 1.92 * @return {@code true} if this list changed as a result of the call
654 jsr166 1.38 * @throws ClassCastException if the class of an element of this list
655 dl 1.73 * is incompatible with the specified collection
656 dl 1.74 * (<a href="../Collection.html#optional-restrictions">optional</a>)
657 jsr166 1.38 * @throws NullPointerException if this list contains a null element and the
658 dl 1.73 * specified collection does not permit null elements
659 dl 1.75 * (<a href="../Collection.html#optional-restrictions">optional</a>),
660 jsr166 1.38 * or if the specified collection is null
661     * @see #remove(Object)
662 tim 1.1 */
663 dl 1.42 public boolean removeAll(Collection<?> c) {
664 dl 1.88 if (c == null) throw new NullPointerException();
665 jsr166 1.67 final ReentrantLock lock = this.lock;
666     lock.lock();
667     try {
668     Object[] elements = getArray();
669     int len = elements.length;
670     if (len != 0) {
671     // temp array holds those elements we know we want to keep
672     int newlen = 0;
673     Object[] temp = new Object[len];
674     for (int i = 0; i < len; ++i) {
675     Object element = elements[i];
676     if (!c.contains(element))
677     temp[newlen++] = element;
678     }
679     if (newlen != len) {
680     setArray(Arrays.copyOf(temp, newlen));
681     return true;
682     }
683     }
684     return false;
685     } finally {
686     lock.unlock();
687     }
688 tim 1.1 }
689    
690     /**
691 jsr166 1.32 * Retains only the elements in this list that are contained in the
692 jsr166 1.35 * specified collection. In other words, removes from this list all of
693     * its elements that are not contained in the specified collection.
694 jsr166 1.32 *
695 jsr166 1.35 * @param c collection containing elements to be retained in this list
696 jsr166 1.92 * @return {@code true} if this list changed as a result of the call
697 jsr166 1.38 * @throws ClassCastException if the class of an element of this list
698 dl 1.73 * is incompatible with the specified collection
699 dl 1.74 * (<a href="../Collection.html#optional-restrictions">optional</a>)
700 jsr166 1.38 * @throws NullPointerException if this list contains a null element and the
701 dl 1.73 * specified collection does not permit null elements
702 dl 1.75 * (<a href="../Collection.html#optional-restrictions">optional</a>),
703 jsr166 1.38 * or if the specified collection is null
704     * @see #remove(Object)
705 tim 1.1 */
706 dl 1.42 public boolean retainAll(Collection<?> c) {
707 dl 1.88 if (c == null) throw new NullPointerException();
708 jsr166 1.67 final ReentrantLock lock = this.lock;
709     lock.lock();
710     try {
711     Object[] elements = getArray();
712     int len = elements.length;
713     if (len != 0) {
714     // temp array holds those elements we know we want to keep
715     int newlen = 0;
716     Object[] temp = new Object[len];
717     for (int i = 0; i < len; ++i) {
718     Object element = elements[i];
719     if (c.contains(element))
720     temp[newlen++] = element;
721     }
722     if (newlen != len) {
723     setArray(Arrays.copyOf(temp, newlen));
724     return true;
725     }
726     }
727     return false;
728     } finally {
729     lock.unlock();
730     }
731 tim 1.1 }
732    
733     /**
734 jsr166 1.32 * Appends all of the elements in the specified collection that
735 tim 1.1 * are not already contained in this list, to the end of
736     * this list, in the order that they are returned by the
737 jsr166 1.32 * specified collection's iterator.
738 tim 1.1 *
739 jsr166 1.36 * @param c collection containing elements to be added to this list
740 tim 1.1 * @return the number of elements added
741 jsr166 1.35 * @throws NullPointerException if the specified collection is null
742 jsr166 1.38 * @see #addIfAbsent(Object)
743 tim 1.1 */
744 dl 1.42 public int addAllAbsent(Collection<? extends E> c) {
745 jsr166 1.67 Object[] cs = c.toArray();
746     if (cs.length == 0)
747     return 0;
748     final ReentrantLock lock = this.lock;
749     lock.lock();
750     try {
751     Object[] elements = getArray();
752     int len = elements.length;
753     int added = 0;
754 jsr166 1.103 // uniquify and compact elements in cs
755     for (int i = 0; i < cs.length; ++i) {
756 jsr166 1.67 Object e = cs[i];
757     if (indexOf(e, elements, 0, len) < 0 &&
758 jsr166 1.103 indexOf(e, cs, 0, added) < 0)
759     cs[added++] = e;
760 jsr166 1.67 }
761     if (added > 0) {
762     Object[] newElements = Arrays.copyOf(elements, len + added);
763 jsr166 1.103 System.arraycopy(cs, 0, newElements, len, added);
764 jsr166 1.67 setArray(newElements);
765     }
766     return added;
767     } finally {
768     lock.unlock();
769     }
770 tim 1.1 }
771    
772     /**
773     * Removes all of the elements from this list.
774 jsr166 1.38 * The list will be empty after this call returns.
775 tim 1.1 */
776 dl 1.42 public void clear() {
777 jsr166 1.67 final ReentrantLock lock = this.lock;
778     lock.lock();
779     try {
780     setArray(new Object[0]);
781     } finally {
782     lock.unlock();
783     }
784 tim 1.1 }
785    
786     /**
787 jsr166 1.32 * Appends all of the elements in the specified collection to the end
788     * of this list, in the order that they are returned by the specified
789     * collection's iterator.
790 tim 1.1 *
791 jsr166 1.36 * @param c collection containing elements to be added to this list
792 jsr166 1.92 * @return {@code true} if this list changed as a result of the call
793 jsr166 1.35 * @throws NullPointerException if the specified collection is null
794 jsr166 1.38 * @see #add(Object)
795 tim 1.1 */
796 dl 1.42 public boolean addAll(Collection<? extends E> c) {
797 dl 1.106 Object[] cs = (c.getClass() == CopyOnWriteArrayList.class) ?
798     ((CopyOnWriteArrayList<?>)c).getArray() : c.toArray();
799 jsr166 1.67 if (cs.length == 0)
800     return false;
801     final ReentrantLock lock = this.lock;
802     lock.lock();
803     try {
804     Object[] elements = getArray();
805     int len = elements.length;
806 dl 1.106 if (len == 0 && cs.getClass() == Object[].class)
807     setArray(cs);
808     else {
809     Object[] newElements = Arrays.copyOf(elements, len + cs.length);
810     System.arraycopy(cs, 0, newElements, len, cs.length);
811     setArray(newElements);
812     }
813 jsr166 1.67 return true;
814     } finally {
815     lock.unlock();
816     }
817 tim 1.1 }
818    
819     /**
820 jsr166 1.35 * Inserts all of the elements in the specified collection into this
821 tim 1.1 * list, starting at the specified position. Shifts the element
822     * currently at that position (if any) and any subsequent elements to
823     * the right (increases their indices). The new elements will appear
824 jsr166 1.38 * in this list in the order that they are returned by the
825     * specified collection's iterator.
826 tim 1.1 *
827 jsr166 1.35 * @param index index at which to insert the first element
828     * from the specified collection
829 jsr166 1.36 * @param c collection containing elements to be added to this list
830 jsr166 1.92 * @return {@code true} if this list changed as a result of the call
831 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
832     * @throws NullPointerException if the specified collection is null
833 jsr166 1.38 * @see #add(int,Object)
834 tim 1.1 */
835 dl 1.42 public boolean addAll(int index, Collection<? extends E> c) {
836 jsr166 1.67 Object[] cs = c.toArray();
837     final ReentrantLock lock = this.lock;
838     lock.lock();
839     try {
840     Object[] elements = getArray();
841     int len = elements.length;
842     if (index > len || index < 0)
843     throw new IndexOutOfBoundsException("Index: "+index+
844     ", Size: "+len);
845     if (cs.length == 0)
846     return false;
847     int numMoved = len - index;
848     Object[] newElements;
849     if (numMoved == 0)
850     newElements = Arrays.copyOf(elements, len + cs.length);
851     else {
852     newElements = new Object[len + cs.length];
853     System.arraycopy(elements, 0, newElements, 0, index);
854     System.arraycopy(elements, index,
855     newElements, index + cs.length,
856     numMoved);
857     }
858     System.arraycopy(cs, 0, newElements, index, cs.length);
859     setArray(newElements);
860     return true;
861     } finally {
862     lock.unlock();
863     }
864 tim 1.1 }
865    
866 dl 1.106 public void forEach(Consumer<? super E> action) {
867     if (action == null) throw new NullPointerException();
868     Object[] elements = getArray();
869     int len = elements.length;
870     for (int i = 0; i < len; ++i) {
871     @SuppressWarnings("unchecked") E e = (E) elements[i];
872     action.accept(e);
873     }
874     }
875    
876     public boolean removeIf(Predicate<? super E> filter) {
877     if (filter == null) throw new NullPointerException();
878     final ReentrantLock lock = this.lock;
879     lock.lock();
880     try {
881     Object[] elements = getArray();
882     int len = elements.length;
883     if (len != 0) {
884     int newlen = 0;
885     Object[] temp = new Object[len];
886     for (int i = 0; i < len; ++i) {
887     @SuppressWarnings("unchecked") E e = (E) elements[i];
888     if (!filter.test(e))
889     temp[newlen++] = e;
890     }
891     if (newlen != len) {
892     setArray(Arrays.copyOf(temp, newlen));
893     return true;
894     }
895     }
896     return false;
897     } finally {
898     lock.unlock();
899     }
900     }
901    
902     public void replaceAll(UnaryOperator<E> operator) {
903 dl 1.108 if (operator == null) throw new NullPointerException();
904 dl 1.106 final ReentrantLock lock = this.lock;
905     lock.lock();
906     try {
907     Object[] elements = getArray();
908     int len = elements.length;
909     Object[] newElements = Arrays.copyOf(elements, len);
910     for (int i = 0; i < len; ++i) {
911     @SuppressWarnings("unchecked") E e = (E) elements[i];
912     newElements[i] = operator.apply(e);
913     }
914     setArray(newElements);
915     } finally {
916     lock.unlock();
917     }
918     }
919    
920     public void sort(Comparator<? super E> c) {
921 jsr166 1.107 final ReentrantLock lock = this.lock;
922     lock.lock();
923     try {
924     Object[] elements = getArray();
925     Object[] newElements = Arrays.copyOf(elements, elements.length);
926     @SuppressWarnings("unchecked") E[] es = (E[])newElements;
927     Arrays.sort(es, c);
928     setArray(newElements);
929 dl 1.106 } finally {
930     lock.unlock();
931     }
932     }
933    
934 tim 1.1 /**
935 jsr166 1.87 * Saves this list to a stream (that is, serializes it).
936 tim 1.1 *
937 jsr166 1.111 * @param s the stream
938 jsr166 1.112 * @throws java.io.IOException if an I/O error occurs
939 tim 1.1 * @serialData The length of the array backing the list is emitted
940     * (int), followed by all of its elements (each an Object)
941     * in the proper order.
942     */
943     private void writeObject(java.io.ObjectOutputStream s)
944 jsr166 1.85 throws java.io.IOException {
945 tim 1.1
946     s.defaultWriteObject();
947    
948 dl 1.41 Object[] elements = getArray();
949 tim 1.1 // Write out array length
950 jsr166 1.71 s.writeInt(elements.length);
951 tim 1.1
952     // Write out all elements in the proper order.
953 jsr166 1.71 for (Object element : elements)
954     s.writeObject(element);
955 tim 1.1 }
956    
957     /**
958 jsr166 1.87 * Reconstitutes this list from a stream (that is, deserializes it).
959 jsr166 1.111 * @param s the stream
960 jsr166 1.112 * @throws ClassNotFoundException if the class of a serialized object
961     * could not be found
962     * @throws java.io.IOException if an I/O error occurs
963 tim 1.1 */
964 dl 1.12 private void readObject(java.io.ObjectInputStream s)
965 tim 1.1 throws java.io.IOException, ClassNotFoundException {
966    
967     s.defaultReadObject();
968    
969 dl 1.42 // bind to new lock
970     resetLock();
971    
972 tim 1.1 // Read in array length and allocate array
973 dl 1.40 int len = s.readInt();
974 dl 1.41 Object[] elements = new Object[len];
975 tim 1.1
976     // Read in all elements in the proper order.
977 dl 1.40 for (int i = 0; i < len; i++)
978 dl 1.41 elements[i] = s.readObject();
979 dl 1.40 setArray(elements);
980 tim 1.1 }
981    
982     /**
983 jsr166 1.55 * Returns a string representation of this list. The string
984     * representation consists of the string representations of the list's
985     * elements in the order they are returned by its iterator, enclosed in
986 jsr166 1.92 * square brackets ({@code "[]"}). Adjacent elements are separated by
987     * the characters {@code ", "} (comma and space). Elements are
988 jsr166 1.55 * converted to strings as by {@link String#valueOf(Object)}.
989     *
990     * @return a string representation of this list
991 tim 1.1 */
992     public String toString() {
993 jsr166 1.67 return Arrays.toString(getArray());
994 tim 1.1 }
995    
996     /**
997 jsr166 1.35 * Compares the specified object with this list for equality.
998 jsr166 1.60 * Returns {@code true} if the specified object is the same object
999     * as this object, or if it is also a {@link List} and the sequence
1000     * of elements returned by an {@linkplain List#iterator() iterator}
1001     * over the specified list is the same as the sequence returned by
1002     * an iterator over this list. The two sequences are considered to
1003     * be the same if they have the same length and corresponding
1004     * elements at the same position in the sequence are <em>equal</em>.
1005     * Two elements {@code e1} and {@code e2} are considered
1006     * <em>equal</em> if {@code (e1==null ? e2==null : e1.equals(e2))}.
1007 tim 1.1 *
1008 jsr166 1.35 * @param o the object to be compared for equality with this list
1009 jsr166 1.60 * @return {@code true} if the specified object is equal to this list
1010 tim 1.1 */
1011     public boolean equals(Object o) {
1012     if (o == this)
1013     return true;
1014     if (!(o instanceof List))
1015     return false;
1016    
1017 dl 1.57 List<?> list = (List<?>)(o);
1018 jsr166 1.67 Iterator<?> it = list.iterator();
1019     Object[] elements = getArray();
1020     int len = elements.length;
1021 jsr166 1.60 for (int i = 0; i < len; ++i)
1022     if (!it.hasNext() || !eq(elements[i], it.next()))
1023 dl 1.57 return false;
1024 jsr166 1.60 if (it.hasNext())
1025 tim 1.1 return false;
1026     return true;
1027     }
1028    
1029     /**
1030 jsr166 1.35 * Returns the hash code value for this list.
1031 dl 1.26 *
1032 jsr166 1.47 * <p>This implementation uses the definition in {@link List#hashCode}.
1033     *
1034     * @return the hash code value for this list
1035 tim 1.1 */
1036     public int hashCode() {
1037     int hashCode = 1;
1038 jsr166 1.67 Object[] elements = getArray();
1039     int len = elements.length;
1040     for (int i = 0; i < len; ++i) {
1041     Object obj = elements[i];
1042 jsr166 1.45 hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
1043 tim 1.1 }
1044     return hashCode;
1045     }
1046    
1047     /**
1048 jsr166 1.35 * Returns an iterator over the elements in this list in proper sequence.
1049     *
1050     * <p>The returned iterator provides a snapshot of the state of the list
1051     * when the iterator was constructed. No synchronization is needed while
1052     * traversing the iterator. The iterator does <em>NOT</em> support the
1053 jsr166 1.92 * {@code remove} method.
1054 jsr166 1.35 *
1055     * @return an iterator over the elements in this list in proper sequence
1056 tim 1.1 */
1057     public Iterator<E> iterator() {
1058 dl 1.40 return new COWIterator<E>(getArray(), 0);
1059 tim 1.1 }
1060    
1061     /**
1062 jsr166 1.35 * {@inheritDoc}
1063 tim 1.1 *
1064 jsr166 1.35 * <p>The returned iterator provides a snapshot of the state of the list
1065     * when the iterator was constructed. No synchronization is needed while
1066     * traversing the iterator. The iterator does <em>NOT</em> support the
1067 jsr166 1.92 * {@code remove}, {@code set} or {@code add} methods.
1068 tim 1.1 */
1069     public ListIterator<E> listIterator() {
1070 dl 1.40 return new COWIterator<E>(getArray(), 0);
1071 tim 1.1 }
1072    
1073     /**
1074 jsr166 1.35 * {@inheritDoc}
1075     *
1076 jsr166 1.50 * <p>The returned iterator provides a snapshot of the state of the list
1077     * when the iterator was constructed. No synchronization is needed while
1078     * traversing the iterator. The iterator does <em>NOT</em> support the
1079 jsr166 1.92 * {@code remove}, {@code set} or {@code add} methods.
1080 jsr166 1.35 *
1081     * @throws IndexOutOfBoundsException {@inheritDoc}
1082 tim 1.1 */
1083 jsr166 1.110 public ListIterator<E> listIterator(int index) {
1084 dl 1.41 Object[] elements = getArray();
1085 dl 1.40 int len = elements.length;
1086 jsr166 1.109 if (index < 0 || index > len)
1087 jsr166 1.45 throw new IndexOutOfBoundsException("Index: "+index);
1088 tim 1.1
1089 dl 1.48 return new COWIterator<E>(elements, index);
1090 tim 1.1 }
1091    
1092 dl 1.100 public Spliterator<E> spliterator() {
1093 dl 1.99 return Spliterators.spliterator
1094 dl 1.98 (getArray(), Spliterator.IMMUTABLE | Spliterator.ORDERED);
1095     }
1096    
1097 dl 1.93 static final class COWIterator<E> implements ListIterator<E> {
1098 jsr166 1.68 /** Snapshot of the array */
1099 dl 1.41 private final Object[] snapshot;
1100 dl 1.40 /** Index of element to be returned by subsequent call to next. */
1101 tim 1.1 private int cursor;
1102    
1103 dl 1.41 private COWIterator(Object[] elements, int initialCursor) {
1104 tim 1.1 cursor = initialCursor;
1105 dl 1.40 snapshot = elements;
1106 tim 1.1 }
1107    
1108     public boolean hasNext() {
1109 dl 1.40 return cursor < snapshot.length;
1110 tim 1.1 }
1111    
1112     public boolean hasPrevious() {
1113     return cursor > 0;
1114     }
1115    
1116 jsr166 1.67 @SuppressWarnings("unchecked")
1117 tim 1.1 public E next() {
1118 jsr166 1.67 if (! hasNext())
1119 tim 1.1 throw new NoSuchElementException();
1120 jsr166 1.67 return (E) snapshot[cursor++];
1121 tim 1.1 }
1122    
1123 jsr166 1.67 @SuppressWarnings("unchecked")
1124 tim 1.1 public E previous() {
1125 jsr166 1.67 if (! hasPrevious())
1126 tim 1.1 throw new NoSuchElementException();
1127 jsr166 1.67 return (E) snapshot[--cursor];
1128 tim 1.1 }
1129    
1130     public int nextIndex() {
1131     return cursor;
1132     }
1133    
1134     public int previousIndex() {
1135 jsr166 1.45 return cursor-1;
1136 tim 1.1 }
1137    
1138     /**
1139     * Not supported. Always throws UnsupportedOperationException.
1140 jsr166 1.92 * @throws UnsupportedOperationException always; {@code remove}
1141 jsr166 1.32 * is not supported by this iterator.
1142 tim 1.1 */
1143     public void remove() {
1144     throw new UnsupportedOperationException();
1145     }
1146    
1147     /**
1148     * Not supported. Always throws UnsupportedOperationException.
1149 jsr166 1.92 * @throws UnsupportedOperationException always; {@code set}
1150 jsr166 1.32 * is not supported by this iterator.
1151 tim 1.1 */
1152 jsr166 1.33 public void set(E e) {
1153 tim 1.1 throw new UnsupportedOperationException();
1154     }
1155    
1156     /**
1157     * Not supported. Always throws UnsupportedOperationException.
1158 jsr166 1.92 * @throws UnsupportedOperationException always; {@code add}
1159 jsr166 1.32 * is not supported by this iterator.
1160 tim 1.1 */
1161 jsr166 1.33 public void add(E e) {
1162 tim 1.1 throw new UnsupportedOperationException();
1163     }
1164     }
1165    
1166     /**
1167 dl 1.40 * Returns a view of the portion of this list between
1168 jsr166 1.92 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
1169 dl 1.40 * The returned list is backed by this list, so changes in the
1170 jsr166 1.66 * returned list are reflected in this list.
1171 dl 1.40 *
1172     * <p>The semantics of the list returned by this method become
1173 jsr166 1.66 * undefined if the backing list (i.e., this list) is modified in
1174     * any way other than via the returned list.
1175 tim 1.1 *
1176 jsr166 1.35 * @param fromIndex low endpoint (inclusive) of the subList
1177     * @param toIndex high endpoint (exclusive) of the subList
1178     * @return a view of the specified range within this list
1179     * @throws IndexOutOfBoundsException {@inheritDoc}
1180 tim 1.1 */
1181 dl 1.42 public List<E> subList(int fromIndex, int toIndex) {
1182 jsr166 1.67 final ReentrantLock lock = this.lock;
1183     lock.lock();
1184     try {
1185     Object[] elements = getArray();
1186     int len = elements.length;
1187     if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
1188     throw new IndexOutOfBoundsException();
1189     return new COWSubList<E>(this, fromIndex, toIndex);
1190     } finally {
1191     lock.unlock();
1192     }
1193 tim 1.1 }
1194    
1195 dl 1.42 /**
1196     * Sublist for CopyOnWriteArrayList.
1197     * This class extends AbstractList merely for convenience, to
1198     * avoid having to define addAll, etc. This doesn't hurt, but
1199     * is wasteful. This class does not need or use modCount
1200     * mechanics in AbstractList, but does need to check for
1201     * concurrent modification using similar mechanics. On each
1202     * operation, the array that we expect the backing list to use
1203     * is checked and updated. Since we do this for all of the
1204     * base operations invoked by those defined in AbstractList,
1205     * all is well. While inefficient, this is not worth
1206     * improving. The kinds of list operations inherited from
1207     * AbstractList are already so slow on COW sublists that
1208     * adding a bit more space/time doesn't seem even noticeable.
1209     */
1210 jsr166 1.66 private static class COWSubList<E>
1211 jsr166 1.67 extends AbstractList<E>
1212     implements RandomAccess
1213 jsr166 1.66 {
1214 tim 1.1 private final CopyOnWriteArrayList<E> l;
1215     private final int offset;
1216     private int size;
1217 dl 1.41 private Object[] expectedArray;
1218 tim 1.1
1219 jsr166 1.45 // only call this holding l's lock
1220 jsr166 1.66 COWSubList(CopyOnWriteArrayList<E> list,
1221 jsr166 1.67 int fromIndex, int toIndex) {
1222 tim 1.1 l = list;
1223 dl 1.40 expectedArray = l.getArray();
1224 tim 1.1 offset = fromIndex;
1225     size = toIndex - fromIndex;
1226     }
1227    
1228     // only call this holding l's lock
1229     private void checkForComodification() {
1230 dl 1.40 if (l.getArray() != expectedArray)
1231 tim 1.1 throw new ConcurrentModificationException();
1232     }
1233    
1234     // only call this holding l's lock
1235     private void rangeCheck(int index) {
1236 jsr166 1.109 if (index < 0 || index >= size)
1237 jsr166 1.45 throw new IndexOutOfBoundsException("Index: "+index+
1238 jsr166 1.67 ",Size: "+size);
1239 tim 1.1 }
1240    
1241     public E set(int index, E element) {
1242 jsr166 1.67 final ReentrantLock lock = l.lock;
1243     lock.lock();
1244     try {
1245 tim 1.1 rangeCheck(index);
1246     checkForComodification();
1247 jsr166 1.45 E x = l.set(index+offset, element);
1248 dl 1.40 expectedArray = l.getArray();
1249 tim 1.1 return x;
1250 jsr166 1.67 } finally {
1251     lock.unlock();
1252     }
1253 tim 1.1 }
1254    
1255     public E get(int index) {
1256 jsr166 1.67 final ReentrantLock lock = l.lock;
1257     lock.lock();
1258     try {
1259 tim 1.1 rangeCheck(index);
1260     checkForComodification();
1261 jsr166 1.45 return l.get(index+offset);
1262 jsr166 1.67 } finally {
1263     lock.unlock();
1264     }
1265 tim 1.1 }
1266    
1267     public int size() {
1268 jsr166 1.67 final ReentrantLock lock = l.lock;
1269     lock.lock();
1270     try {
1271 tim 1.1 checkForComodification();
1272     return size;
1273 jsr166 1.67 } finally {
1274     lock.unlock();
1275     }
1276 tim 1.1 }
1277    
1278     public void add(int index, E element) {
1279 jsr166 1.67 final ReentrantLock lock = l.lock;
1280     lock.lock();
1281     try {
1282 tim 1.1 checkForComodification();
1283 jsr166 1.109 if (index < 0 || index > size)
1284 tim 1.1 throw new IndexOutOfBoundsException();
1285 jsr166 1.45 l.add(index+offset, element);
1286 dl 1.40 expectedArray = l.getArray();
1287 tim 1.1 size++;
1288 jsr166 1.67 } finally {
1289     lock.unlock();
1290     }
1291 tim 1.1 }
1292    
1293 dl 1.13 public void clear() {
1294 jsr166 1.67 final ReentrantLock lock = l.lock;
1295     lock.lock();
1296     try {
1297 dl 1.13 checkForComodification();
1298     l.removeRange(offset, offset+size);
1299 dl 1.40 expectedArray = l.getArray();
1300 dl 1.13 size = 0;
1301 jsr166 1.67 } finally {
1302     lock.unlock();
1303     }
1304 dl 1.13 }
1305    
1306 tim 1.1 public E remove(int index) {
1307 jsr166 1.67 final ReentrantLock lock = l.lock;
1308     lock.lock();
1309     try {
1310 tim 1.1 rangeCheck(index);
1311     checkForComodification();
1312 jsr166 1.45 E result = l.remove(index+offset);
1313 dl 1.40 expectedArray = l.getArray();
1314 tim 1.1 size--;
1315     return result;
1316 jsr166 1.67 } finally {
1317     lock.unlock();
1318     }
1319 tim 1.1 }
1320    
1321 jsr166 1.66 public boolean remove(Object o) {
1322 jsr166 1.67 int index = indexOf(o);
1323     if (index == -1)
1324     return false;
1325     remove(index);
1326     return true;
1327 jsr166 1.66 }
1328    
1329 tim 1.1 public Iterator<E> iterator() {
1330 jsr166 1.67 final ReentrantLock lock = l.lock;
1331     lock.lock();
1332     try {
1333 tim 1.1 checkForComodification();
1334 tim 1.8 return new COWSubListIterator<E>(l, 0, offset, size);
1335 jsr166 1.67 } finally {
1336     lock.unlock();
1337     }
1338 tim 1.1 }
1339    
1340 jsr166 1.110 public ListIterator<E> listIterator(int index) {
1341 jsr166 1.67 final ReentrantLock lock = l.lock;
1342     lock.lock();
1343     try {
1344 tim 1.1 checkForComodification();
1345 jsr166 1.109 if (index < 0 || index > size)
1346 dl 1.40 throw new IndexOutOfBoundsException("Index: "+index+
1347 jsr166 1.67 ", Size: "+size);
1348 tim 1.8 return new COWSubListIterator<E>(l, index, offset, size);
1349 jsr166 1.67 } finally {
1350     lock.unlock();
1351     }
1352 tim 1.1 }
1353    
1354 tim 1.7 public List<E> subList(int fromIndex, int toIndex) {
1355 jsr166 1.67 final ReentrantLock lock = l.lock;
1356     lock.lock();
1357     try {
1358 tim 1.7 checkForComodification();
1359 jsr166 1.109 if (fromIndex < 0 || toIndex > size)
1360 tim 1.7 throw new IndexOutOfBoundsException();
1361 dl 1.41 return new COWSubList<E>(l, fromIndex + offset,
1362 jsr166 1.67 toIndex + offset);
1363     } finally {
1364     lock.unlock();
1365     }
1366 tim 1.7 }
1367 tim 1.1
1368 dl 1.106 public void forEach(Consumer<? super E> action) {
1369     if (action == null) throw new NullPointerException();
1370     int lo = offset;
1371     int hi = offset + size;
1372     Object[] a = expectedArray;
1373     if (l.getArray() != a)
1374     throw new ConcurrentModificationException();
1375 dl 1.108 if (lo < 0 || hi > a.length)
1376     throw new IndexOutOfBoundsException();
1377 dl 1.106 for (int i = lo; i < hi; ++i) {
1378     @SuppressWarnings("unchecked") E e = (E) a[i];
1379     action.accept(e);
1380     }
1381     }
1382    
1383 dl 1.108 public void replaceAll(UnaryOperator<E> operator) {
1384     if (operator == null) throw new NullPointerException();
1385     final ReentrantLock lock = l.lock;
1386     lock.lock();
1387     try {
1388     int lo = offset;
1389     int hi = offset + size;
1390     Object[] elements = expectedArray;
1391     if (l.getArray() != elements)
1392     throw new ConcurrentModificationException();
1393     int len = elements.length;
1394     if (lo < 0 || hi > len)
1395     throw new IndexOutOfBoundsException();
1396     Object[] newElements = Arrays.copyOf(elements, len);
1397     for (int i = lo; i < hi; ++i) {
1398     @SuppressWarnings("unchecked") E e = (E) elements[i];
1399     newElements[i] = operator.apply(e);
1400     }
1401     l.setArray(expectedArray = newElements);
1402     } finally {
1403     lock.unlock();
1404     }
1405     }
1406    
1407     public void sort(Comparator<? super E> c) {
1408     final ReentrantLock lock = l.lock;
1409     lock.lock();
1410     try {
1411     int lo = offset;
1412     int hi = offset + size;
1413     Object[] elements = expectedArray;
1414     if (l.getArray() != elements)
1415     throw new ConcurrentModificationException();
1416     int len = elements.length;
1417     if (lo < 0 || hi > len)
1418     throw new IndexOutOfBoundsException();
1419     Object[] newElements = Arrays.copyOf(elements, len);
1420     @SuppressWarnings("unchecked") E[] es = (E[])newElements;
1421     Arrays.sort(es, lo, hi, c);
1422     l.setArray(expectedArray = newElements);
1423     } finally {
1424     lock.unlock();
1425     }
1426     }
1427    
1428     public boolean removeAll(Collection<?> c) {
1429     if (c == null) throw new NullPointerException();
1430     boolean removed = false;
1431     final ReentrantLock lock = l.lock;
1432     lock.lock();
1433     try {
1434     int n = size;
1435     if (n > 0) {
1436     int lo = offset;
1437     int hi = offset + n;
1438     Object[] elements = expectedArray;
1439     if (l.getArray() != elements)
1440     throw new ConcurrentModificationException();
1441     int len = elements.length;
1442     if (lo < 0 || hi > len)
1443     throw new IndexOutOfBoundsException();
1444     int newSize = 0;
1445     Object[] temp = new Object[n];
1446     for (int i = lo; i < hi; ++i) {
1447     Object element = elements[i];
1448     if (!c.contains(element))
1449     temp[newSize++] = element;
1450     }
1451     if (newSize != n) {
1452     Object[] newElements = new Object[len - n + newSize];
1453     System.arraycopy(elements, 0, newElements, 0, lo);
1454     System.arraycopy(temp, 0, newElements, lo, newSize);
1455     System.arraycopy(elements, hi, newElements,
1456     lo + newSize, len - hi);
1457     size = newSize;
1458     removed = true;
1459     l.setArray(expectedArray = newElements);
1460     }
1461     }
1462     } finally {
1463     lock.unlock();
1464     }
1465     return removed;
1466     }
1467    
1468     public boolean retainAll(Collection<?> c) {
1469     if (c == null) throw new NullPointerException();
1470     boolean removed = false;
1471     final ReentrantLock lock = l.lock;
1472     lock.lock();
1473     try {
1474     int n = size;
1475     if (n > 0) {
1476     int lo = offset;
1477     int hi = offset + n;
1478     Object[] elements = expectedArray;
1479     if (l.getArray() != elements)
1480     throw new ConcurrentModificationException();
1481     int len = elements.length;
1482     if (lo < 0 || hi > len)
1483     throw new IndexOutOfBoundsException();
1484     int newSize = 0;
1485     Object[] temp = new Object[n];
1486     for (int i = lo; i < hi; ++i) {
1487     Object element = elements[i];
1488     if (c.contains(element))
1489     temp[newSize++] = element;
1490     }
1491     if (newSize != n) {
1492     Object[] newElements = new Object[len - n + newSize];
1493     System.arraycopy(elements, 0, newElements, 0, lo);
1494     System.arraycopy(temp, 0, newElements, lo, newSize);
1495     System.arraycopy(elements, hi, newElements,
1496     lo + newSize, len - hi);
1497     size = newSize;
1498     removed = true;
1499     l.setArray(expectedArray = newElements);
1500     }
1501     }
1502     } finally {
1503     lock.unlock();
1504     }
1505     return removed;
1506     }
1507    
1508     public boolean removeIf(Predicate<? super E> filter) {
1509     if (filter == null) throw new NullPointerException();
1510     boolean removed = false;
1511     final ReentrantLock lock = l.lock;
1512     lock.lock();
1513     try {
1514     int n = size;
1515     if (n > 0) {
1516     int lo = offset;
1517     int hi = offset + n;
1518     Object[] elements = expectedArray;
1519     if (l.getArray() != elements)
1520     throw new ConcurrentModificationException();
1521     int len = elements.length;
1522     if (lo < 0 || hi > len)
1523     throw new IndexOutOfBoundsException();
1524     int newSize = 0;
1525     Object[] temp = new Object[n];
1526     for (int i = lo; i < hi; ++i) {
1527     @SuppressWarnings("unchecked") E e = (E) elements[i];
1528     if (!filter.test(e))
1529     temp[newSize++] = e;
1530     }
1531     if (newSize != n) {
1532     Object[] newElements = new Object[len - n + newSize];
1533     System.arraycopy(elements, 0, newElements, 0, lo);
1534     System.arraycopy(temp, 0, newElements, lo, newSize);
1535     System.arraycopy(elements, hi, newElements,
1536     lo + newSize, len - hi);
1537     size = newSize;
1538     removed = true;
1539     l.setArray(expectedArray = newElements);
1540     }
1541     }
1542     } finally {
1543     lock.unlock();
1544     }
1545     return removed;
1546     }
1547    
1548 dl 1.100 public Spliterator<E> spliterator() {
1549 dl 1.93 int lo = offset;
1550     int hi = offset + size;
1551     Object[] a = expectedArray;
1552     if (l.getArray() != a)
1553     throw new ConcurrentModificationException();
1554     if (lo < 0 || hi > a.length)
1555     throw new IndexOutOfBoundsException();
1556 dl 1.99 return Spliterators.spliterator
1557 dl 1.98 (a, lo, hi, Spliterator.IMMUTABLE | Spliterator.ORDERED);
1558     }
1559    
1560 tim 1.7 }
1561 tim 1.1
1562 tim 1.7 private static class COWSubListIterator<E> implements ListIterator<E> {
1563 jsr166 1.80 private final ListIterator<E> it;
1564 tim 1.7 private final int offset;
1565     private final int size;
1566 jsr166 1.66
1567 jsr166 1.79 COWSubListIterator(List<E> l, int index, int offset, int size) {
1568 tim 1.7 this.offset = offset;
1569     this.size = size;
1570 jsr166 1.80 it = l.listIterator(index+offset);
1571 tim 1.7 }
1572 tim 1.1
1573 tim 1.7 public boolean hasNext() {
1574     return nextIndex() < size;
1575     }
1576 tim 1.1
1577 tim 1.7 public E next() {
1578     if (hasNext())
1579 jsr166 1.80 return it.next();
1580 tim 1.7 else
1581     throw new NoSuchElementException();
1582     }
1583 tim 1.1
1584 tim 1.7 public boolean hasPrevious() {
1585     return previousIndex() >= 0;
1586     }
1587 tim 1.1
1588 tim 1.7 public E previous() {
1589     if (hasPrevious())
1590 jsr166 1.80 return it.previous();
1591 tim 1.7 else
1592     throw new NoSuchElementException();
1593     }
1594 tim 1.1
1595 tim 1.7 public int nextIndex() {
1596 jsr166 1.80 return it.nextIndex() - offset;
1597 tim 1.7 }
1598 tim 1.1
1599 tim 1.7 public int previousIndex() {
1600 jsr166 1.80 return it.previousIndex() - offset;
1601 tim 1.1 }
1602    
1603 tim 1.7 public void remove() {
1604     throw new UnsupportedOperationException();
1605     }
1606 tim 1.1
1607 jsr166 1.33 public void set(E e) {
1608 tim 1.7 throw new UnsupportedOperationException();
1609 tim 1.1 }
1610    
1611 jsr166 1.33 public void add(E e) {
1612 tim 1.7 throw new UnsupportedOperationException();
1613     }
1614 tim 1.1 }
1615    
1616 dl 1.42 // Support for resetting lock while deserializing
1617 dl 1.72 private void resetLock() {
1618     UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock());
1619     }
1620     private static final sun.misc.Unsafe UNSAFE;
1621 dl 1.42 private static final long lockOffset;
1622     static {
1623     try {
1624 dl 1.72 UNSAFE = sun.misc.Unsafe.getUnsafe();
1625 jsr166 1.76 Class<?> k = CopyOnWriteArrayList.class;
1626 dl 1.72 lockOffset = UNSAFE.objectFieldOffset
1627     (k.getDeclaredField("lock"));
1628     } catch (Exception e) {
1629     throw new Error(e);
1630     }
1631 dl 1.42 }
1632 tim 1.1 }