ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.125
Committed: Sun Jan 25 20:37:11 2015 UTC (9 years, 4 months ago) by jsr166
Branch: MAIN
Changes since 1.124: +12 -10 lines
Log Message:
refactor out-of-bounds exception message string

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