ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.149
Committed: Tue Apr 3 18:52:18 2018 UTC (6 years, 2 months ago) by jsr166
Branch: MAIN
Changes since 1.148: +9 -9 lines
Log Message:
rangeCheckForAdd

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
19 import java.lang.reflect.Field;
20 import java.util.Arrays;
21 import java.util.Collection;
22 import java.util.Comparator;
23 import java.util.ConcurrentModificationException;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.ListIterator;
27 import java.util.NoSuchElementException;
28 import java.util.Objects;
29 import java.util.RandomAccess;
30 import java.util.Spliterator;
31 import java.util.Spliterators;
32 import java.util.function.Consumer;
33 import java.util.function.Predicate;
34 import java.util.function.UnaryOperator;
35 import jdk.internal.misc.SharedSecrets;
36
37 /**
38 * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
39 * operations ({@code add}, {@code set}, and so on) are implemented by
40 * making a fresh copy of the underlying array.
41 *
42 * <p>This is ordinarily too costly, but may be <em>more</em> efficient
43 * 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 * 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 * guaranteed not to throw {@code ConcurrentModificationException}.
51 * The iterator will not reflect additions, removals, or changes to
52 * the list since the iterator was created. Element-changing
53 * operations on iterators themselves ({@code remove}, {@code set}, and
54 * {@code add}) are not supported. These methods throw
55 * {@code UnsupportedOperationException}.
56 *
57 * <p>All elements are permitted, including {@code null}.
58 *
59 * <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 * <p>This class is a member of the
67 * <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
68 * Java Collections Framework</a>.
69 *
70 * @since 1.5
71 * @author Doug Lea
72 * @param <E> the type of elements held in this list
73 */
74 public class CopyOnWriteArrayList<E>
75 implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
76 private static final long serialVersionUID = 8673264195747942595L;
77
78 /**
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
84 /** The array, accessed only via getArray/setArray. */
85 private transient volatile Object[] array;
86
87 /**
88 * Gets the array. Non-private so as to also be accessible
89 * from CopyOnWriteArraySet class.
90 */
91 final Object[] getArray() {
92 return array;
93 }
94
95 /**
96 * Sets the array.
97 */
98 final void setArray(Object[] a) {
99 array = a;
100 }
101
102 /**
103 * Creates an empty list.
104 */
105 public CopyOnWriteArrayList() {
106 setArray(new Object[0]);
107 }
108
109 /**
110 * Creates a list containing the elements of the specified
111 * collection, in the order they are returned by the collection's
112 * iterator.
113 *
114 * @param c the collection of initially held elements
115 * @throws NullPointerException if the specified collection is null
116 */
117 public CopyOnWriteArrayList(Collection<? extends E> c) {
118 Object[] es;
119 if (c.getClass() == CopyOnWriteArrayList.class)
120 es = ((CopyOnWriteArrayList<?>)c).getArray();
121 else {
122 es = c.toArray();
123 // defend against c.toArray (incorrectly) not returning Object[]
124 // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
125 if (es.getClass() != Object[].class)
126 es = Arrays.copyOf(es, es.length, Object[].class);
127 }
128 setArray(es);
129 }
130
131 /**
132 * Creates a list holding a copy of the given array.
133 *
134 * @param toCopyIn the array (a copy of this array is used as the
135 * internal array)
136 * @throws NullPointerException if the specified array is null
137 */
138 public CopyOnWriteArrayList(E[] toCopyIn) {
139 setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
140 }
141
142 /**
143 * Returns the number of elements in this list.
144 *
145 * @return the number of elements in this list
146 */
147 public int size() {
148 return getArray().length;
149 }
150
151 /**
152 * Returns {@code true} if this list contains no elements.
153 *
154 * @return {@code true} if this list contains no elements
155 */
156 public boolean isEmpty() {
157 return size() == 0;
158 }
159
160 /**
161 * static version of indexOf, to allow repeated calls without
162 * needing to re-acquire array each time.
163 * @param o element to search for
164 * @param es the array
165 * @param from first index to search
166 * @param to one past last index to search
167 * @return index of element, or -1 if absent
168 */
169 private static int indexOfRange(Object o, Object[] es, int from, int to) {
170 if (o == null) {
171 for (int i = from; i < to; i++)
172 if (es[i] == null)
173 return i;
174 } else {
175 for (int i = from; i < to; i++)
176 if (o.equals(es[i]))
177 return i;
178 }
179 return -1;
180 }
181
182 /**
183 * static version of lastIndexOf.
184 * @param o element to search for
185 * @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 * @return index of element, or -1 if absent
189 */
190 private static int lastIndexOfRange(Object o, Object[] es, int from, int to) {
191 if (o == null) {
192 for (int i = to - 1; i >= from; i--)
193 if (es[i] == null)
194 return i;
195 } else {
196 for (int i = to - 1; i >= from; i--)
197 if (o.equals(es[i]))
198 return i;
199 }
200 return -1;
201 }
202
203 /**
204 * Returns {@code true} if this list contains the specified element.
205 * More formally, returns {@code true} if and only if this list contains
206 * at least one element {@code e} such that {@code Objects.equals(o, e)}.
207 *
208 * @param o element whose presence in this list is to be tested
209 * @return {@code true} if this list contains the specified element
210 */
211 public boolean contains(Object o) {
212 return indexOf(o) >= 0;
213 }
214
215 /**
216 * {@inheritDoc}
217 */
218 public int indexOf(Object o) {
219 Object[] es = getArray();
220 return indexOfRange(o, es, 0, es.length);
221 }
222
223 /**
224 * Returns the index of the first occurrence of the specified element in
225 * this list, searching forwards from {@code index}, or returns -1 if
226 * the element is not found.
227 * More formally, returns the lowest index {@code i} such that
228 * {@code i >= index && Objects.equals(get(i), e)},
229 * 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 * this list at position {@code index} or later in the list;
235 * {@code -1} if the element is not found.
236 * @throws IndexOutOfBoundsException if the specified index is negative
237 */
238 public int indexOf(E e, int index) {
239 Object[] es = getArray();
240 return indexOfRange(e, es, index, es.length);
241 }
242
243 /**
244 * {@inheritDoc}
245 */
246 public int lastIndexOf(Object o) {
247 Object[] es = getArray();
248 return lastIndexOfRange(o, es, 0, es.length);
249 }
250
251 /**
252 * Returns the index of the last occurrence of the specified element in
253 * this list, searching backwards from {@code index}, or returns -1 if
254 * the element is not found.
255 * More formally, returns the highest index {@code i} such that
256 * {@code i <= index && Objects.equals(get(i), e)},
257 * 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 * less than or equal to {@code index} in this list;
263 * -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 */
267 public int lastIndexOf(E e, int index) {
268 Object[] es = getArray();
269 return lastIndexOfRange(e, es, 0, index + 1);
270 }
271
272 /**
273 * Returns a shallow copy of this list. (The elements themselves
274 * are not copied.)
275 *
276 * @return a clone of this list
277 */
278 public Object clone() {
279 try {
280 @SuppressWarnings("unchecked")
281 CopyOnWriteArrayList<E> clone =
282 (CopyOnWriteArrayList<E>) super.clone();
283 clone.resetLock();
284 return clone;
285 } 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 * 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 *
299 * <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 */
304 public Object[] toArray() {
305 return getArray().clone();
306 }
307
308 /**
309 * 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 *
316 * <p>If this list fits in the specified array with room to spare
317 * (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 * {@code null}. (This is useful in determining the length of this
320 * 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 * <p>Suppose {@code x} is a list known to contain only strings.
329 * The following code can be used to dump the list into a newly
330 * allocated array of {@code String}:
331 *
332 * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
333 *
334 * Note that {@code toArray(new Object[0])} is identical in function to
335 * {@code toArray()}.
336 *
337 * @param a the array into which the elements of the list are to
338 * 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 */
346 @SuppressWarnings("unchecked")
347 public <T> T[] toArray(T[] a) {
348 Object[] es = getArray();
349 int len = es.length;
350 if (a.length < len)
351 return (T[]) Arrays.copyOf(es, len, a.getClass());
352 else {
353 System.arraycopy(es, 0, a, 0, len);
354 if (a.length > len)
355 a[len] = null;
356 return a;
357 }
358 }
359
360 // Positional Access Operations
361
362 @SuppressWarnings("unchecked")
363 static <E> E elementAt(Object[] a, int index) {
364 return (E) a[index];
365 }
366
367 static String outOfBounds(int index, int size) {
368 return "Index: " + index + ", Size: " + size;
369 }
370
371 /**
372 * {@inheritDoc}
373 *
374 * @throws IndexOutOfBoundsException {@inheritDoc}
375 */
376 public E get(int index) {
377 return elementAt(getArray(), index);
378 }
379
380 /**
381 * Replaces the element at the specified position in this list with the
382 * specified element.
383 *
384 * @throws IndexOutOfBoundsException {@inheritDoc}
385 */
386 public E set(int index, E element) {
387 synchronized (lock) {
388 Object[] es = getArray();
389 E oldValue = elementAt(es, index);
390
391 if (oldValue != element) {
392 es = es.clone();
393 es[index] = element;
394 setArray(es);
395 }
396 return oldValue;
397 }
398 }
399
400 /**
401 * Appends the specified element to the end of this list.
402 *
403 * @param e element to be appended to this list
404 * @return {@code true} (as specified by {@link Collection#add})
405 */
406 public boolean add(E e) {
407 synchronized (lock) {
408 Object[] es = getArray();
409 int len = es.length;
410 es = Arrays.copyOf(es, len + 1);
411 es[len] = e;
412 setArray(es);
413 return true;
414 }
415 }
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 * @throws IndexOutOfBoundsException {@inheritDoc}
423 */
424 public void add(int index, E element) {
425 synchronized (lock) {
426 Object[] es = getArray();
427 int len = es.length;
428 if (index > len || index < 0)
429 throw new IndexOutOfBoundsException(outOfBounds(index, len));
430 Object[] newElements;
431 int numMoved = len - index;
432 if (numMoved == 0)
433 newElements = Arrays.copyOf(es, len + 1);
434 else {
435 newElements = new Object[len + 1];
436 System.arraycopy(es, 0, newElements, 0, index);
437 System.arraycopy(es, index, newElements, index + 1,
438 numMoved);
439 }
440 newElements[index] = element;
441 setArray(newElements);
442 }
443 }
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 * indices). Returns the element that was removed from the list.
449 *
450 * @throws IndexOutOfBoundsException {@inheritDoc}
451 */
452 public E remove(int index) {
453 synchronized (lock) {
454 Object[] es = getArray();
455 int len = es.length;
456 E oldValue = elementAt(es, index);
457 int numMoved = len - index - 1;
458 Object[] newElements;
459 if (numMoved == 0)
460 newElements = Arrays.copyOf(es, len - 1);
461 else {
462 newElements = new Object[len - 1];
463 System.arraycopy(es, 0, newElements, 0, index);
464 System.arraycopy(es, index + 1, newElements, index,
465 numMoved);
466 }
467 setArray(newElements);
468 return oldValue;
469 }
470 }
471
472 /**
473 * 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 * {@code i} such that {@code Objects.equals(o, get(i))}
477 * (if such an element exists). Returns {@code true} if this list
478 * contained the specified element (or equivalently, if this list
479 * changed as a result of the call).
480 *
481 * @param o element to be removed from this list, if present
482 * @return {@code true} if this list contained the specified element
483 */
484 public boolean remove(Object o) {
485 Object[] snapshot = getArray();
486 int index = indexOfRange(o, snapshot, 0, snapshot.length);
487 return index >= 0 && remove(o, snapshot, index);
488 }
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 synchronized (lock) {
496 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 if (current[i] != snapshot[i]
502 && Objects.equals(o, current[i])) {
503 index = i;
504 break findIndex;
505 }
506 }
507 if (index >= len)
508 return false;
509 if (current[index] == o)
510 break findIndex;
511 index = indexOfRange(o, current, index, len);
512 if (index < 0)
513 return false;
514 }
515 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 }
523 }
524
525 /**
526 * Removes from this list all of the elements whose index is between
527 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
528 * Shifts any succeeding elements to the left (reduces their index).
529 * This call shortens the list by {@code (toIndex - fromIndex)} elements.
530 * (If {@code toIndex==fromIndex}, this operation has no effect.)
531 *
532 * @param fromIndex index of first element to be removed
533 * @param toIndex index after last element to be removed
534 * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range
535 * ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
536 */
537 void removeRange(int fromIndex, int toIndex) {
538 synchronized (lock) {
539 Object[] es = getArray();
540 int len = es.length;
541
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 setArray(Arrays.copyOf(es, newlen));
548 else {
549 Object[] newElements = new Object[newlen];
550 System.arraycopy(es, 0, newElements, 0, fromIndex);
551 System.arraycopy(es, toIndex, newElements,
552 fromIndex, numMoved);
553 setArray(newElements);
554 }
555 }
556 }
557
558 /**
559 * Appends the element, if not present.
560 *
561 * @param e element to be added to this list, if absent
562 * @return {@code true} if the element was added
563 */
564 public boolean addIfAbsent(E e) {
565 Object[] snapshot = getArray();
566 return indexOfRange(e, snapshot, 0, snapshot.length) < 0
567 && addIfAbsent(e, snapshot);
568 }
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 synchronized (lock) {
576 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 if (current[i] != snapshot[i]
583 && Objects.equals(e, current[i]))
584 return false;
585 if (indexOfRange(e, current, common, len) >= 0)
586 return false;
587 }
588 Object[] newElements = Arrays.copyOf(current, len + 1);
589 newElements[len] = e;
590 setArray(newElements);
591 return true;
592 }
593 }
594
595 /**
596 * Returns {@code true} if this list contains all of the elements of the
597 * specified collection.
598 *
599 * @param c collection to be checked for containment in this list
600 * @return {@code true} if this list contains all of the elements of the
601 * specified collection
602 * @throws NullPointerException if the specified collection is null
603 * @see #contains(Object)
604 */
605 public boolean containsAll(Collection<?> c) {
606 Object[] es = getArray();
607 int len = es.length;
608 for (Object e : c) {
609 if (indexOfRange(e, es, 0, len) < 0)
610 return false;
611 }
612 return true;
613 }
614
615 /**
616 * Removes from this list all of its elements that are contained in
617 * the specified collection. This is a particularly expensive operation
618 * in this class because of the need for an internal temporary array.
619 *
620 * @param c collection containing elements to be removed from this list
621 * @return {@code true} if this list changed as a result of the call
622 * @throws ClassCastException if the class of an element of this list
623 * is incompatible with the specified collection
624 * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>)
625 * @throws NullPointerException if this list contains a null element and the
626 * specified collection does not permit null elements
627 * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>),
628 * or if the specified collection is null
629 * @see #remove(Object)
630 */
631 public boolean removeAll(Collection<?> c) {
632 Objects.requireNonNull(c);
633 return bulkRemove(e -> c.contains(e));
634 }
635
636 /**
637 * Retains only the elements in this list that are contained in the
638 * specified collection. In other words, removes from this list all of
639 * its elements that are not contained in the specified collection.
640 *
641 * @param c collection containing elements to be retained in this list
642 * @return {@code true} if this list changed as a result of the call
643 * @throws ClassCastException if the class of an element of this list
644 * is incompatible with the specified collection
645 * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>)
646 * @throws NullPointerException if this list contains a null element and the
647 * specified collection does not permit null elements
648 * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>),
649 * or if the specified collection is null
650 * @see #remove(Object)
651 */
652 public boolean retainAll(Collection<?> c) {
653 Objects.requireNonNull(c);
654 return bulkRemove(e -> !c.contains(e));
655 }
656
657 /**
658 * Appends all of the elements in the specified collection that
659 * are not already contained in this list, to the end of
660 * this list, in the order that they are returned by the
661 * specified collection's iterator.
662 *
663 * @param c collection containing elements to be added to this list
664 * @return the number of elements added
665 * @throws NullPointerException if the specified collection is null
666 * @see #addIfAbsent(Object)
667 */
668 public int addAllAbsent(Collection<? extends E> c) {
669 Object[] cs = c.toArray();
670 if (cs.length == 0)
671 return 0;
672 synchronized (lock) {
673 Object[] es = getArray();
674 int len = es.length;
675 int added = 0;
676 // uniquify and compact elements in cs
677 for (int i = 0; i < cs.length; ++i) {
678 Object e = cs[i];
679 if (indexOfRange(e, es, 0, len) < 0 &&
680 indexOfRange(e, cs, 0, added) < 0)
681 cs[added++] = e;
682 }
683 if (added > 0) {
684 Object[] newElements = Arrays.copyOf(es, len + added);
685 System.arraycopy(cs, 0, newElements, len, added);
686 setArray(newElements);
687 }
688 return added;
689 }
690 }
691
692 /**
693 * Removes all of the elements from this list.
694 * The list will be empty after this call returns.
695 */
696 public void clear() {
697 synchronized (lock) {
698 setArray(new Object[0]);
699 }
700 }
701
702 /**
703 * 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 *
707 * @param c collection containing elements to be added to this list
708 * @return {@code true} if this list changed as a result of the call
709 * @throws NullPointerException if the specified collection is null
710 * @see #add(Object)
711 */
712 public boolean addAll(Collection<? extends E> c) {
713 Object[] cs = (c.getClass() == CopyOnWriteArrayList.class) ?
714 ((CopyOnWriteArrayList<?>)c).getArray() : c.toArray();
715 if (cs.length == 0)
716 return false;
717 synchronized (lock) {
718 Object[] es = getArray();
719 int len = es.length;
720 Object[] newElements;
721 if (len == 0 && cs.getClass() == Object[].class)
722 newElements = cs;
723 else {
724 newElements = Arrays.copyOf(es, len + cs.length);
725 System.arraycopy(cs, 0, newElements, len, cs.length);
726 }
727 setArray(newElements);
728 return true;
729 }
730 }
731
732 /**
733 * Inserts all of the elements in the specified collection into this
734 * 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 * in this list in the order that they are returned by the
738 * specified collection's iterator.
739 *
740 * @param index index at which to insert the first element
741 * from the specified collection
742 * @param c collection containing elements to be added to this list
743 * @return {@code true} if this list changed as a result of the call
744 * @throws IndexOutOfBoundsException {@inheritDoc}
745 * @throws NullPointerException if the specified collection is null
746 * @see #add(int,Object)
747 */
748 public boolean addAll(int index, Collection<? extends E> c) {
749 Object[] cs = c.toArray();
750 synchronized (lock) {
751 Object[] es = getArray();
752 int len = es.length;
753 if (index > len || index < 0)
754 throw new IndexOutOfBoundsException(outOfBounds(index, len));
755 if (cs.length == 0)
756 return false;
757 int numMoved = len - index;
758 Object[] newElements;
759 if (numMoved == 0)
760 newElements = Arrays.copyOf(es, len + cs.length);
761 else {
762 newElements = new Object[len + cs.length];
763 System.arraycopy(es, 0, newElements, 0, index);
764 System.arraycopy(es, index,
765 newElements, index + cs.length,
766 numMoved);
767 }
768 System.arraycopy(cs, 0, newElements, index, cs.length);
769 setArray(newElements);
770 return true;
771 }
772 }
773
774 /**
775 * @throws NullPointerException {@inheritDoc}
776 */
777 public void forEach(Consumer<? super E> action) {
778 Objects.requireNonNull(action);
779 for (Object x : getArray()) {
780 @SuppressWarnings("unchecked") E e = (E) x;
781 action.accept(e);
782 }
783 }
784
785 /**
786 * @throws NullPointerException {@inheritDoc}
787 */
788 public boolean removeIf(Predicate<? super E> filter) {
789 Objects.requireNonNull(filter);
790 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 synchronized (lock) {
807 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 }
827 // 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 }
843 }
844
845 public void replaceAll(UnaryOperator<E> operator) {
846 Objects.requireNonNull(operator);
847 synchronized (lock) {
848 replaceAllRange(operator, 0, getArray().length);
849 }
850 }
851
852 void replaceAllRange(UnaryOperator<E> operator, int i, int end) {
853 // 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 public void sort(Comparator<? super E> c) {
861 synchronized (lock) {
862 sortRange(c, 0, getArray().length);
863 }
864 }
865
866 @SuppressWarnings("unchecked")
867 void sortRange(Comparator<? super E> c, int i, int end) {
868 // 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 /**
875 * Saves this list to a stream (that is, serializes it).
876 *
877 * @param s the stream
878 * @throws java.io.IOException if an I/O error occurs
879 * @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 throws java.io.IOException {
885
886 s.defaultWriteObject();
887
888 Object[] es = getArray();
889 // Write out array length
890 s.writeInt(es.length);
891
892 // Write out all elements in the proper order.
893 for (Object element : es)
894 s.writeObject(element);
895 }
896
897 /**
898 * Reconstitutes this list from a stream (that is, deserializes it).
899 * @param s the stream
900 * @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 */
904 private void readObject(java.io.ObjectInputStream s)
905 throws java.io.IOException, ClassNotFoundException {
906
907 s.defaultReadObject();
908
909 // bind to new lock
910 resetLock();
911
912 // Read in array length and allocate array
913 int len = s.readInt();
914 SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, len);
915 Object[] es = new Object[len];
916
917 // Read in all elements in the proper order.
918 for (int i = 0; i < len; i++)
919 es[i] = s.readObject();
920 setArray(es);
921 }
922
923 /**
924 * 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 * square brackets ({@code "[]"}). Adjacent elements are separated by
928 * the characters {@code ", "} (comma and space). Elements are
929 * converted to strings as by {@link String#valueOf(Object)}.
930 *
931 * @return a string representation of this list
932 */
933 public String toString() {
934 return Arrays.toString(getArray());
935 }
936
937 /**
938 * Compares the specified object with this list for equality.
939 * 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 * <em>equal</em> if {@code Objects.equals(e1, e2)}.
948 *
949 * @param o the object to be compared for equality with this list
950 * @return {@code true} if the specified object is equal to this list
951 */
952 public boolean equals(Object o) {
953 if (o == this)
954 return true;
955 if (!(o instanceof List))
956 return false;
957
958 List<?> list = (List<?>)o;
959 Iterator<?> it = list.iterator();
960 for (Object element : getArray())
961 if (!it.hasNext() || !Objects.equals(element, it.next()))
962 return false;
963 return !it.hasNext();
964 }
965
966 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 /**
976 * Returns the hash code value for this list.
977 *
978 * <p>This implementation uses the definition in {@link List#hashCode}.
979 *
980 * @return the hash code value for this list
981 */
982 public int hashCode() {
983 Object[] es = getArray();
984 return hashCodeOfRange(es, 0, es.length);
985 }
986
987 /**
988 * 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 * {@code remove} method.
994 *
995 * @return an iterator over the elements in this list in proper sequence
996 */
997 public Iterator<E> iterator() {
998 return new COWIterator<E>(getArray(), 0);
999 }
1000
1001 /**
1002 * {@inheritDoc}
1003 *
1004 * <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 * {@code remove}, {@code set} or {@code add} methods.
1008 */
1009 public ListIterator<E> listIterator() {
1010 return new COWIterator<E>(getArray(), 0);
1011 }
1012
1013 /**
1014 * {@inheritDoc}
1015 *
1016 * <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 * {@code remove}, {@code set} or {@code add} methods.
1020 *
1021 * @throws IndexOutOfBoundsException {@inheritDoc}
1022 */
1023 public ListIterator<E> listIterator(int index) {
1024 Object[] es = getArray();
1025 int len = es.length;
1026 if (index < 0 || index > len)
1027 throw new IndexOutOfBoundsException(outOfBounds(index, len));
1028
1029 return new COWIterator<E>(es, index);
1030 }
1031
1032 /**
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 * operating on the spliterator.
1042 *
1043 * @return a {@code Spliterator} over the elements in this list
1044 * @since 1.8
1045 */
1046 public Spliterator<E> spliterator() {
1047 return Spliterators.spliterator
1048 (getArray(), Spliterator.IMMUTABLE | Spliterator.ORDERED);
1049 }
1050
1051 static final class COWIterator<E> implements ListIterator<E> {
1052 /** Snapshot of the array */
1053 private final Object[] snapshot;
1054 /** Index of element to be returned by subsequent call to next. */
1055 private int cursor;
1056
1057 COWIterator(Object[] es, int initialCursor) {
1058 cursor = initialCursor;
1059 snapshot = es;
1060 }
1061
1062 public boolean hasNext() {
1063 return cursor < snapshot.length;
1064 }
1065
1066 public boolean hasPrevious() {
1067 return cursor > 0;
1068 }
1069
1070 @SuppressWarnings("unchecked")
1071 public E next() {
1072 if (! hasNext())
1073 throw new NoSuchElementException();
1074 return (E) snapshot[cursor++];
1075 }
1076
1077 @SuppressWarnings("unchecked")
1078 public E previous() {
1079 if (! hasPrevious())
1080 throw new NoSuchElementException();
1081 return (E) snapshot[--cursor];
1082 }
1083
1084 public int nextIndex() {
1085 return cursor;
1086 }
1087
1088 public int previousIndex() {
1089 return cursor - 1;
1090 }
1091
1092 /**
1093 * Not supported. Always throws UnsupportedOperationException.
1094 * @throws UnsupportedOperationException always; {@code remove}
1095 * is not supported by this iterator.
1096 */
1097 public void remove() {
1098 throw new UnsupportedOperationException();
1099 }
1100
1101 /**
1102 * Not supported. Always throws UnsupportedOperationException.
1103 * @throws UnsupportedOperationException always; {@code set}
1104 * is not supported by this iterator.
1105 */
1106 public void set(E e) {
1107 throw new UnsupportedOperationException();
1108 }
1109
1110 /**
1111 * Not supported. Always throws UnsupportedOperationException.
1112 * @throws UnsupportedOperationException always; {@code add}
1113 * is not supported by this iterator.
1114 */
1115 public void add(E e) {
1116 throw new UnsupportedOperationException();
1117 }
1118
1119 @Override
1120 public void forEachRemaining(Consumer<? super E> action) {
1121 Objects.requireNonNull(action);
1122 final int size = snapshot.length;
1123 int i = cursor;
1124 cursor = size;
1125 for (; i < size; i++)
1126 action.accept(elementAt(snapshot, i));
1127 }
1128 }
1129
1130 /**
1131 * Returns a view of the portion of this list between
1132 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
1133 * The returned list is backed by this list, so changes in the
1134 * returned list are reflected in this list.
1135 *
1136 * <p>The semantics of the list returned by this method become
1137 * undefined if the backing list (i.e., this list) is modified in
1138 * any way other than via the returned list.
1139 *
1140 * @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 */
1145 public List<E> subList(int fromIndex, int toIndex) {
1146 synchronized (lock) {
1147 Object[] es = getArray();
1148 int len = es.length;
1149 int size = toIndex - fromIndex;
1150 if (fromIndex < 0 || toIndex > len || size < 0)
1151 throw new IndexOutOfBoundsException();
1152 return new COWSubList(es, fromIndex, size);
1153 }
1154 }
1155
1156 /**
1157 * Sublist for CopyOnWriteArrayList.
1158 */
1159 private class COWSubList implements List<E>, RandomAccess {
1160 private final int offset;
1161 private int size;
1162 private Object[] expectedArray;
1163
1164 COWSubList(Object[] es, int offset, int size) {
1165 // assert Thread.holdsLock(lock);
1166 expectedArray = es;
1167 this.offset = offset;
1168 this.size = size;
1169 }
1170
1171 private void checkForComodification() {
1172 // assert Thread.holdsLock(lock);
1173 if (getArray() != expectedArray)
1174 throw new ConcurrentModificationException();
1175 }
1176
1177 private Object[] getArrayChecked() {
1178 // assert Thread.holdsLock(lock);
1179 Object[] a = getArray();
1180 if (a != expectedArray)
1181 throw new ConcurrentModificationException();
1182 return a;
1183 }
1184
1185 private void rangeCheck(int index) {
1186 // assert Thread.holdsLock(lock);
1187 if (index < 0 || index >= size)
1188 throw new IndexOutOfBoundsException(outOfBounds(index, size));
1189 }
1190
1191 private void rangeCheckForAdd(int index) {
1192 // assert Thread.holdsLock(lock);
1193 if (index < 0 || index > size)
1194 throw new IndexOutOfBoundsException(outOfBounds(index, size));
1195 }
1196
1197 public Object[] toArray() {
1198 final Object[] es;
1199 final int offset;
1200 final int size;
1201 synchronized (lock) {
1202 es = getArrayChecked();
1203 offset = this.offset;
1204 size = this.size;
1205 }
1206 return Arrays.copyOfRange(es, offset, offset + size);
1207 }
1208
1209 @SuppressWarnings("unchecked")
1210 public <T> T[] toArray(T[] a) {
1211 final Object[] es;
1212 final int offset;
1213 final int size;
1214 synchronized (lock) {
1215 es = getArrayChecked();
1216 offset = this.offset;
1217 size = this.size;
1218 }
1219 if (a.length < size)
1220 return (T[]) Arrays.copyOfRange(
1221 es, offset, offset + size, a.getClass());
1222 else {
1223 System.arraycopy(es, offset, a, 0, size);
1224 if (a.length > size)
1225 a[size] = null;
1226 return a;
1227 }
1228 }
1229
1230 public int indexOf(Object o) {
1231 final Object[] es;
1232 final int offset;
1233 final int size;
1234 synchronized (lock) {
1235 es = getArrayChecked();
1236 offset = this.offset;
1237 size = this.size;
1238 }
1239 int i = indexOfRange(o, es, offset, offset + size);
1240 return (i == -1) ? -1 : i - offset;
1241 }
1242
1243 public int lastIndexOf(Object o) {
1244 final Object[] es;
1245 final int offset;
1246 final int size;
1247 synchronized (lock) {
1248 es = getArrayChecked();
1249 offset = this.offset;
1250 size = this.size;
1251 }
1252 int i = lastIndexOfRange(o, es, offset, offset + size);
1253 return (i == -1) ? -1 : i - offset;
1254 }
1255
1256 public boolean contains(Object o) {
1257 return indexOf(o) >= 0;
1258 }
1259
1260 public boolean containsAll(Collection<?> c) {
1261 final Object[] es;
1262 final int offset;
1263 final int size;
1264 synchronized (lock) {
1265 es = getArrayChecked();
1266 offset = this.offset;
1267 size = this.size;
1268 }
1269 for (Object o : c)
1270 if (indexOfRange(o, es, offset, offset + size) < 0)
1271 return false;
1272 return true;
1273 }
1274
1275 public boolean isEmpty() {
1276 return size() == 0;
1277 }
1278
1279 public String toString() {
1280 return Arrays.toString(toArray());
1281 }
1282
1283 public int hashCode() {
1284 final Object[] es;
1285 final int offset;
1286 final int size;
1287 synchronized (lock) {
1288 es = getArrayChecked();
1289 offset = this.offset;
1290 size = this.size;
1291 }
1292 return hashCodeOfRange(es, offset, offset + size);
1293 }
1294
1295 public boolean equals(Object o) {
1296 if (o == this)
1297 return true;
1298 if (!(o instanceof List))
1299 return false;
1300
1301 final Object[] es;
1302 final int offset;
1303 final int size;
1304 synchronized (lock) {
1305 es = getArrayChecked();
1306 offset = this.offset;
1307 size = this.size;
1308 }
1309
1310 List<?> list = (List<?>)o;
1311 Iterator<?> it = list.iterator();
1312 for (int i = offset, end = offset + size; i < end; i++)
1313 if (!it.hasNext() || !Objects.equals(es[i], it.next()))
1314 return false;
1315 return !it.hasNext();
1316 }
1317
1318 public E set(int index, E element) {
1319 synchronized (lock) {
1320 rangeCheck(index);
1321 checkForComodification();
1322 E x = CopyOnWriteArrayList.this.set(offset + index, element);
1323 expectedArray = getArray();
1324 return x;
1325 }
1326 }
1327
1328 public E get(int index) {
1329 synchronized (lock) {
1330 rangeCheck(index);
1331 checkForComodification();
1332 return CopyOnWriteArrayList.this.get(offset + index);
1333 }
1334 }
1335
1336 public int size() {
1337 synchronized (lock) {
1338 checkForComodification();
1339 return size;
1340 }
1341 }
1342
1343 public boolean add(E element) {
1344 synchronized (lock) {
1345 checkForComodification();
1346 CopyOnWriteArrayList.this.add(offset + size, element);
1347 expectedArray = getArray();
1348 size++;
1349 }
1350 return true;
1351 }
1352
1353 public void add(int index, E element) {
1354 synchronized (lock) {
1355 checkForComodification();
1356 rangeCheckForAdd(index);
1357 CopyOnWriteArrayList.this.add(offset + index, element);
1358 expectedArray = getArray();
1359 size++;
1360 }
1361 }
1362
1363 public boolean addAll(Collection<? extends E> c) {
1364 synchronized (lock) {
1365 final Object[] oldArray = getArrayChecked();
1366 boolean modified =
1367 CopyOnWriteArrayList.this.addAll(offset + size, c);
1368 size += (expectedArray = getArray()).length - oldArray.length;
1369 return modified;
1370 }
1371 }
1372
1373 public boolean addAll(int index, Collection<? extends E> c) {
1374 synchronized (lock) {
1375 rangeCheckForAdd(index);
1376 final Object[] oldArray = getArrayChecked();
1377 boolean modified =
1378 CopyOnWriteArrayList.this.addAll(offset + index, c);
1379 size += (expectedArray = getArray()).length - oldArray.length;
1380 return modified;
1381 }
1382 }
1383
1384 public void clear() {
1385 synchronized (lock) {
1386 checkForComodification();
1387 removeRange(offset, offset + size);
1388 expectedArray = getArray();
1389 size = 0;
1390 }
1391 }
1392
1393 public E remove(int index) {
1394 synchronized (lock) {
1395 rangeCheck(index);
1396 checkForComodification();
1397 E result = CopyOnWriteArrayList.this.remove(offset + index);
1398 expectedArray = getArray();
1399 size--;
1400 return result;
1401 }
1402 }
1403
1404 public boolean remove(Object o) {
1405 synchronized (lock) {
1406 checkForComodification();
1407 int index = indexOf(o);
1408 if (index == -1)
1409 return false;
1410 remove(index);
1411 return true;
1412 }
1413 }
1414
1415 public Iterator<E> iterator() {
1416 return listIterator(0);
1417 }
1418
1419 public ListIterator<E> listIterator() {
1420 return listIterator(0);
1421 }
1422
1423 public ListIterator<E> listIterator(int index) {
1424 synchronized (lock) {
1425 checkForComodification();
1426 rangeCheckForAdd(index);
1427 return new COWSubListIterator<E>(
1428 CopyOnWriteArrayList.this, index, offset, size);
1429 }
1430 }
1431
1432 public List<E> subList(int fromIndex, int toIndex) {
1433 synchronized (lock) {
1434 checkForComodification();
1435 if (fromIndex < 0 || toIndex > size || fromIndex > toIndex)
1436 throw new IndexOutOfBoundsException();
1437 return new COWSubList(expectedArray, fromIndex + offset, toIndex - fromIndex);
1438 }
1439 }
1440
1441 public void forEach(Consumer<? super E> action) {
1442 Objects.requireNonNull(action);
1443 int i, end; final Object[] es;
1444 synchronized (lock) {
1445 es = getArrayChecked();
1446 i = offset;
1447 end = i + size;
1448 }
1449 for (; i < end; i++)
1450 action.accept(elementAt(es, i));
1451 }
1452
1453 public void replaceAll(UnaryOperator<E> operator) {
1454 Objects.requireNonNull(operator);
1455 synchronized (lock) {
1456 checkForComodification();
1457 replaceAllRange(operator, offset, offset + size);
1458 expectedArray = getArray();
1459 }
1460 }
1461
1462 public void sort(Comparator<? super E> c) {
1463 synchronized (lock) {
1464 checkForComodification();
1465 sortRange(c, offset, offset + size);
1466 expectedArray = getArray();
1467 }
1468 }
1469
1470 public boolean removeAll(Collection<?> c) {
1471 Objects.requireNonNull(c);
1472 return bulkRemove(e -> c.contains(e));
1473 }
1474
1475 public boolean retainAll(Collection<?> c) {
1476 Objects.requireNonNull(c);
1477 return bulkRemove(e -> !c.contains(e));
1478 }
1479
1480 public boolean removeIf(Predicate<? super E> filter) {
1481 Objects.requireNonNull(filter);
1482 return bulkRemove(filter);
1483 }
1484
1485 private boolean bulkRemove(Predicate<? super E> filter) {
1486 synchronized (lock) {
1487 final Object[] oldArray = getArrayChecked();
1488 boolean modified = CopyOnWriteArrayList.this.bulkRemove(
1489 filter, offset, offset + size);
1490 size += (expectedArray = getArray()).length - oldArray.length;
1491 return modified;
1492 }
1493 }
1494
1495 public Spliterator<E> spliterator() {
1496 synchronized (lock) {
1497 return Spliterators.spliterator(
1498 getArrayChecked(), offset, offset + size,
1499 Spliterator.IMMUTABLE | Spliterator.ORDERED);
1500 }
1501 }
1502
1503 }
1504
1505 private static class COWSubListIterator<E> implements ListIterator<E> {
1506 private final ListIterator<E> it;
1507 private final int offset;
1508 private final int size;
1509
1510 COWSubListIterator(List<E> l, int index, int offset, int size) {
1511 this.offset = offset;
1512 this.size = size;
1513 it = l.listIterator(index + offset);
1514 }
1515
1516 public boolean hasNext() {
1517 return nextIndex() < size;
1518 }
1519
1520 public E next() {
1521 if (hasNext())
1522 return it.next();
1523 else
1524 throw new NoSuchElementException();
1525 }
1526
1527 public boolean hasPrevious() {
1528 return previousIndex() >= 0;
1529 }
1530
1531 public E previous() {
1532 if (hasPrevious())
1533 return it.previous();
1534 else
1535 throw new NoSuchElementException();
1536 }
1537
1538 public int nextIndex() {
1539 return it.nextIndex() - offset;
1540 }
1541
1542 public int previousIndex() {
1543 return it.previousIndex() - offset;
1544 }
1545
1546 public void remove() {
1547 throw new UnsupportedOperationException();
1548 }
1549
1550 public void set(E e) {
1551 throw new UnsupportedOperationException();
1552 }
1553
1554 public void add(E e) {
1555 throw new UnsupportedOperationException();
1556 }
1557
1558 @Override
1559 @SuppressWarnings("unchecked")
1560 public void forEachRemaining(Consumer<? super E> action) {
1561 Objects.requireNonNull(action);
1562 while (hasNext()) {
1563 action.accept(it.next());
1564 }
1565 }
1566 }
1567
1568 /** Initializes the lock; for use when deserializing or cloning. */
1569 private void resetLock() {
1570 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 try {
1581 lockField.set(this, new Object());
1582 } catch (IllegalAccessException e) {
1583 throw new Error(e);
1584 }
1585 }
1586 }