ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.139
Committed: Sun Jun 5 20:41:14 2016 UTC (7 years, 11 months ago) by jsr166
Branch: MAIN
Changes since 1.138: +1 -1 lines
Log Message:
appease spell checker

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