ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.158
Committed: Fri Mar 18 16:01:41 2022 UTC (2 years, 2 months ago) by dl
Branch: MAIN
CVS Tags: HEAD
Changes since 1.157: +1 -0 lines
Log Message:
jdk17+ suppressWarnings, FJ updates

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