ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.148
Committed: Tue Apr 3 16:32:40 2018 UTC (6 years, 2 months ago) by jsr166
Branch: MAIN
Changes since 1.147: +317 -187 lines
Log Message:
Optimize COWAL sublists; stop subclassing AbstractList

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