ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.130
Committed: Wed May 20 05:57:05 2015 UTC (9 years ago) by jsr166
Branch: MAIN
Changes since 1.129: +18 -13 lines
Log Message:
optimize removeIf for zero or one match

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