ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.105
Committed: Thu May 2 06:00:07 2013 UTC (11 years, 1 month ago) by jsr166
Branch: MAIN
Changes since 1.104: +0 -1 lines
Log Message:
port to latest lambda

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