ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.93
Committed: Wed Jan 16 15:04:03 2013 UTC (11 years, 4 months ago) by dl
Branch: MAIN
Changes since 1.92: +113 -2 lines
Log Message:
lambda-lib support

File Contents

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