ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.98
Committed: Sun Feb 17 23:36:34 2013 UTC (11 years, 3 months ago) by dl
Branch: MAIN
Changes since 1.97: +23 -78 lines
Log Message:
Spliterator sync

File Contents

# User Rev Content
1 dl 1.2 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3 dl 1.17 * Expert Group. Adapted and released, under explicit permission,
4 dl 1.15 * from JDK ArrayList.java which carries the following copyright:
5 dl 1.3 *
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 dl 1.2 */
16    
17 tim 1.1 package java.util.concurrent;
18 dl 1.98 import java.util.AbstractList;
19 dl 1.93 import java.util.Arrays;
20     import java.util.Collection;
21 dl 1.98 import java.util.Collections;
22     import java.util.ConcurrentModificationException;
23     import java.util.Iterator;
24 dl 1.93 import java.util.List;
25     import java.util.ListIterator;
26 dl 1.98 import java.util.NoSuchElementException;
27 dl 1.93 import java.util.RandomAccess;
28     import java.util.Spliterator;
29 dl 1.98 import java.util.concurrent.locks.ReentrantLock;
30     import java.util.function.Consumer;
31 dl 1.93 import java.util.stream.Stream;
32     import java.util.stream.Streams;
33 tim 1.1
34     /**
35 dl 1.28 * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
36 jsr166 1.92 * operations ({@code add}, {@code set}, and so on) are implemented by
37 jsr166 1.35 * making a fresh copy of the underlying array.
38 tim 1.1 *
39 jsr166 1.91 * <p>This is ordinarily too costly, but may be <em>more</em> efficient
40 dl 1.12 * 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 dl 1.15 * 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 jsr166 1.92 * guaranteed not to throw {@code ConcurrentModificationException}.
48 dl 1.15 * The iterator will not reflect additions, removals, or changes to
49     * the list since the iterator was created. Element-changing
50 jsr166 1.92 * operations on iterators themselves ({@code remove}, {@code set}, and
51     * {@code add}) are not supported. These methods throw
52     * {@code UnsupportedOperationException}.
53 dl 1.24 *
54 jsr166 1.92 * <p>All elements are permitted, including {@code null}.
55 jsr166 1.35 *
56 jsr166 1.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 dl 1.24 * <p>This class is a member of the
64 jsr166 1.64 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
65 dl 1.24 * Java Collections Framework</a>.
66     *
67 dl 1.6 * @since 1.5
68     * @author Doug Lea
69 dl 1.19 * @param <E> the type of elements held in this collection
70 dl 1.6 */
71 tim 1.1 public class CopyOnWriteArrayList<E>
72 dl 1.40 implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
73 dl 1.11 private static final long serialVersionUID = 8673264195747942595L;
74 tim 1.1
75 dl 1.42 /** The lock protecting all mutators */
76 jsr166 1.95 final transient ReentrantLock lock = new ReentrantLock();
77 dl 1.42
78 dl 1.40 /** The array, accessed only via getArray/setArray. */
79 jsr166 1.95 private transient volatile Object[] array;
80 tim 1.1
81 dl 1.57 /**
82 jsr166 1.60 * Gets the array. Non-private so as to also be accessible
83     * from CopyOnWriteArraySet class.
84 dl 1.57 */
85 jsr166 1.63 final Object[] getArray() {
86 jsr166 1.59 return array;
87 dl 1.57 }
88    
89     /**
90 jsr166 1.60 * Sets the array.
91 dl 1.57 */
92 jsr166 1.59 final void setArray(Object[] a) {
93     array = a;
94 dl 1.57 }
95 tim 1.1
96     /**
97 dl 1.15 * Creates an empty list.
98 tim 1.1 */
99     public CopyOnWriteArrayList() {
100 dl 1.41 setArray(new Object[0]);
101 tim 1.1 }
102    
103     /**
104 dl 1.15 * Creates a list containing the elements of the specified
105 jsr166 1.32 * collection, in the order they are returned by the collection's
106 tim 1.1 * iterator.
107 jsr166 1.32 *
108 dl 1.6 * @param c the collection of initially held elements
109 jsr166 1.35 * @throws NullPointerException if the specified collection is null
110 tim 1.1 */
111 tim 1.22 public CopyOnWriteArrayList(Collection<? extends E> c) {
112 jsr166 1.67 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 tim 1.1 }
118    
119     /**
120 jsr166 1.35 * Creates a list holding a copy of the given array.
121 tim 1.9 *
122     * @param toCopyIn the array (a copy of this array is used as the
123     * internal array)
124 jsr166 1.38 * @throws NullPointerException if the specified array is null
125 jsr166 1.30 */
126 tim 1.1 public CopyOnWriteArrayList(E[] toCopyIn) {
127 jsr166 1.67 setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
128 tim 1.1 }
129    
130     /**
131 dl 1.15 * Returns the number of elements in this list.
132 tim 1.1 *
133 jsr166 1.35 * @return the number of elements in this list
134 tim 1.1 */
135     public int size() {
136 dl 1.40 return getArray().length;
137 tim 1.1 }
138    
139     /**
140 jsr166 1.92 * Returns {@code true} if this list contains no elements.
141 tim 1.1 *
142 jsr166 1.92 * @return {@code true} if this list contains no elements
143 tim 1.1 */
144     public boolean isEmpty() {
145     return size() == 0;
146     }
147    
148 dl 1.43 /**
149 jsr166 1.90 * Tests for equality, coping with nulls.
150 dl 1.43 */
151     private static boolean eq(Object o1, Object o2) {
152     return (o1 == null ? o2 == null : o1.equals(o2));
153     }
154    
155 dl 1.41 /**
156 dl 1.40 * static version of indexOf, to allow repeated calls without
157 dl 1.41 * needing to re-acquire array each time.
158 dl 1.40 * @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 dl 1.41 private static int indexOf(Object o, Object[] elements,
165 dl 1.40 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 dl 1.41
178     /**
179 dl 1.40 * 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 tim 1.1 /**
199 jsr166 1.92 * 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 jsr166 1.35 * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
203 tim 1.1 *
204 jsr166 1.35 * @param o element whose presence in this list is to be tested
205 jsr166 1.92 * @return {@code true} if this list contains the specified element
206 tim 1.1 */
207 jsr166 1.35 public boolean contains(Object o) {
208 dl 1.41 Object[] elements = getArray();
209 dl 1.40 return indexOf(o, elements, 0, elements.length) >= 0;
210 tim 1.1 }
211    
212     /**
213 jsr166 1.35 * {@inheritDoc}
214 tim 1.1 */
215 jsr166 1.35 public int indexOf(Object o) {
216 dl 1.41 Object[] elements = getArray();
217 dl 1.40 return indexOf(o, elements, 0, elements.length);
218 tim 1.1 }
219    
220     /**
221 jsr166 1.35 * Returns the index of the first occurrence of the specified element in
222 jsr166 1.92 * this list, searching forwards from {@code index}, or returns -1 if
223 jsr166 1.35 * the element is not found.
224 jsr166 1.92 * More formally, returns the lowest index {@code i} such that
225 jsr166 1.35 * <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 jsr166 1.92 * this list at position {@code index} or later in the list;
232     * {@code -1} if the element is not found.
233 jsr166 1.35 * @throws IndexOutOfBoundsException if the specified index is negative
234 tim 1.1 */
235 jsr166 1.35 public int indexOf(E e, int index) {
236 dl 1.41 Object[] elements = getArray();
237 jsr166 1.67 return indexOf(e, elements, index, elements.length);
238 tim 1.1 }
239    
240     /**
241 jsr166 1.35 * {@inheritDoc}
242 tim 1.1 */
243 jsr166 1.35 public int lastIndexOf(Object o) {
244 dl 1.41 Object[] elements = getArray();
245 dl 1.40 return lastIndexOf(o, elements, elements.length - 1);
246 tim 1.1 }
247    
248     /**
249 jsr166 1.35 * Returns the index of the last occurrence of the specified element in
250 jsr166 1.92 * this list, searching backwards from {@code index}, or returns -1 if
251 jsr166 1.35 * the element is not found.
252 jsr166 1.92 * More formally, returns the highest index {@code i} such that
253 jsr166 1.35 * <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 jsr166 1.92 * less than or equal to {@code index} in this list;
260 jsr166 1.35 * -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 tim 1.1 */
264 jsr166 1.35 public int lastIndexOf(E e, int index) {
265 dl 1.41 Object[] elements = getArray();
266 jsr166 1.67 return lastIndexOf(e, elements, index);
267 tim 1.1 }
268    
269     /**
270     * Returns a shallow copy of this list. (The elements themselves
271     * are not copied.)
272     *
273 jsr166 1.35 * @return a clone of this list
274 tim 1.1 */
275     public Object clone() {
276     try {
277 jsr166 1.83 @SuppressWarnings("unchecked")
278     CopyOnWriteArrayList<E> clone =
279     (CopyOnWriteArrayList<E>) super.clone();
280     clone.resetLock();
281     return clone;
282 tim 1.1 } 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 jsr166 1.35 * 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 jsr166 1.36 *
296 jsr166 1.35 * <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 tim 1.1 */
301     public Object[] toArray() {
302 dl 1.40 Object[] elements = getArray();
303 jsr166 1.67 return Arrays.copyOf(elements, elements.length);
304 tim 1.1 }
305    
306     /**
307 jsr166 1.35 * 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 jsr166 1.32 *
314     * <p>If this list fits in the specified array with room to spare
315 jsr166 1.35 * (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 jsr166 1.92 * {@code null}. (This is useful in determining the length of this
318 jsr166 1.35 * 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 jsr166 1.92 * <p>Suppose {@code x} is a list known to contain only strings.
327 jsr166 1.35 * The following code can be used to dump the list into a newly
328 jsr166 1.92 * allocated array of {@code String}:
329 jsr166 1.35 *
330 jsr166 1.81 * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
331 jsr166 1.35 *
332 jsr166 1.92 * Note that {@code toArray(new Object[0])} is identical in function to
333     * {@code toArray()}.
334 tim 1.1 *
335     * @param a the array into which the elements of the list are to
336 jsr166 1.35 * 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 tim 1.1 */
344 jsr166 1.66 @SuppressWarnings("unchecked")
345 tim 1.1 public <T> T[] toArray(T a[]) {
346 dl 1.41 Object[] elements = getArray();
347 dl 1.40 int len = elements.length;
348     if (a.length < len)
349 jsr166 1.67 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 tim 1.1 }
357    
358     // Positional Access Operations
359    
360 jsr166 1.66 @SuppressWarnings("unchecked")
361     private E get(Object[] a, int index) {
362 jsr166 1.67 return (E) a[index];
363 jsr166 1.66 }
364    
365 tim 1.1 /**
366 jsr166 1.35 * {@inheritDoc}
367 tim 1.1 *
368 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
369 tim 1.1 */
370     public E get(int index) {
371 jsr166 1.66 return get(getArray(), index);
372 tim 1.1 }
373    
374     /**
375 jsr166 1.35 * Replaces the element at the specified position in this list with the
376     * specified element.
377 tim 1.1 *
378 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
379 tim 1.1 */
380 dl 1.42 public E set(int index, E element) {
381 jsr166 1.67 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 tim 1.1 }
401    
402     /**
403     * Appends the specified element to the end of this list.
404     *
405 dl 1.40 * @param e element to be appended to this list
406 jsr166 1.92 * @return {@code true} (as specified by {@link Collection#add})
407 tim 1.1 */
408 dl 1.42 public boolean add(E e) {
409 jsr166 1.67 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 tim 1.1 }
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 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
429 tim 1.1 */
430 dl 1.42 public void add(int index, E element) {
431 jsr166 1.67 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 tim 1.1 }
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 jsr166 1.35 * indices). Returns the element that was removed from the list.
460 tim 1.1 *
461 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
462 tim 1.1 */
463 dl 1.42 public E remove(int index) {
464 jsr166 1.67 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 tim 1.1 }
485    
486     /**
487 jsr166 1.35 * 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 jsr166 1.92 * {@code i} such that
491 jsr166 1.35 * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
492 jsr166 1.92 * (if such an element exists). Returns {@code true} if this list
493 jsr166 1.35 * contained the specified element (or equivalently, if this list
494     * changed as a result of the call).
495 tim 1.1 *
496 jsr166 1.35 * @param o element to be removed from this list, if present
497 jsr166 1.92 * @return {@code true} if this list contained the specified element
498 tim 1.1 */
499 dl 1.42 public boolean remove(Object o) {
500 jsr166 1.67 final ReentrantLock lock = this.lock;
501     lock.lock();
502     try {
503     Object[] elements = getArray();
504     int len = elements.length;
505     if (len != 0) {
506     // Copy while searching for element to remove
507     // This wins in the normal case of element being present
508     int newlen = len - 1;
509     Object[] newElements = new Object[newlen];
510    
511     for (int i = 0; i < newlen; ++i) {
512     if (eq(o, elements[i])) {
513     // found one; copy remaining and exit
514     for (int k = i + 1; k < len; ++k)
515     newElements[k-1] = elements[k];
516     setArray(newElements);
517     return true;
518     } else
519     newElements[i] = elements[i];
520     }
521    
522     // special handling for last cell
523     if (eq(o, elements[newlen])) {
524     setArray(newElements);
525     return true;
526     }
527     }
528     return false;
529     } finally {
530     lock.unlock();
531     }
532 tim 1.1 }
533    
534     /**
535 jsr166 1.35 * Removes from this list all of the elements whose index is between
536 jsr166 1.92 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
537 jsr166 1.35 * Shifts any succeeding elements to the left (reduces their index).
538 jsr166 1.92 * This call shortens the list by {@code (toIndex - fromIndex)} elements.
539     * (If {@code toIndex==fromIndex}, this operation has no effect.)
540 tim 1.1 *
541 jsr166 1.35 * @param fromIndex index of first element to be removed
542     * @param toIndex index after last element to be removed
543 jsr166 1.66 * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range
544 jsr166 1.86 * ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
545 tim 1.1 */
546 jsr166 1.84 void removeRange(int fromIndex, int toIndex) {
547 jsr166 1.67 final ReentrantLock lock = this.lock;
548     lock.lock();
549     try {
550     Object[] elements = getArray();
551     int len = elements.length;
552    
553     if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
554     throw new IndexOutOfBoundsException();
555     int newlen = len - (toIndex - fromIndex);
556     int numMoved = len - toIndex;
557     if (numMoved == 0)
558     setArray(Arrays.copyOf(elements, newlen));
559     else {
560     Object[] newElements = new Object[newlen];
561     System.arraycopy(elements, 0, newElements, 0, fromIndex);
562     System.arraycopy(elements, toIndex, newElements,
563     fromIndex, numMoved);
564     setArray(newElements);
565     }
566     } finally {
567     lock.unlock();
568     }
569 tim 1.1 }
570    
571     /**
572 jsr166 1.90 * Appends the element, if not present.
573 jsr166 1.38 *
574 dl 1.40 * @param e element to be added to this list, if absent
575 jsr166 1.92 * @return {@code true} if the element was added
576 jsr166 1.30 */
577 dl 1.42 public boolean addIfAbsent(E e) {
578 jsr166 1.67 final ReentrantLock lock = this.lock;
579     lock.lock();
580     try {
581     // Copy while checking if already present.
582     // This wins in the most common case where it is not present
583     Object[] elements = getArray();
584     int len = elements.length;
585     Object[] newElements = new Object[len + 1];
586     for (int i = 0; i < len; ++i) {
587     if (eq(e, elements[i]))
588     return false; // exit, throwing away copy
589     else
590     newElements[i] = elements[i];
591     }
592     newElements[len] = e;
593     setArray(newElements);
594     return true;
595     } finally {
596     lock.unlock();
597     }
598 tim 1.1 }
599    
600     /**
601 jsr166 1.92 * Returns {@code true} if this list contains all of the elements of the
602 jsr166 1.32 * specified collection.
603 jsr166 1.34 *
604 jsr166 1.36 * @param c collection to be checked for containment in this list
605 jsr166 1.92 * @return {@code true} if this list contains all of the elements of the
606 jsr166 1.35 * specified collection
607     * @throws NullPointerException if the specified collection is null
608 jsr166 1.38 * @see #contains(Object)
609 tim 1.1 */
610 tim 1.7 public boolean containsAll(Collection<?> c) {
611 dl 1.41 Object[] elements = getArray();
612 dl 1.40 int len = elements.length;
613 jsr166 1.67 for (Object e : c) {
614 dl 1.41 if (indexOf(e, elements, 0, len) < 0)
615 tim 1.1 return false;
616 jsr166 1.67 }
617 tim 1.1 return true;
618     }
619    
620     /**
621 jsr166 1.32 * Removes from this list all of its elements that are contained in
622     * the specified collection. This is a particularly expensive operation
623 tim 1.1 * in this class because of the need for an internal temporary array.
624     *
625 jsr166 1.35 * @param c collection containing elements to be removed from this list
626 jsr166 1.92 * @return {@code true} if this list changed as a result of the call
627 jsr166 1.38 * @throws ClassCastException if the class of an element of this list
628 dl 1.73 * is incompatible with the specified collection
629 dl 1.74 * (<a href="../Collection.html#optional-restrictions">optional</a>)
630 jsr166 1.38 * @throws NullPointerException if this list contains a null element and the
631 dl 1.73 * specified collection does not permit null elements
632 dl 1.75 * (<a href="../Collection.html#optional-restrictions">optional</a>),
633 jsr166 1.38 * or if the specified collection is null
634     * @see #remove(Object)
635 tim 1.1 */
636 dl 1.42 public boolean removeAll(Collection<?> c) {
637 dl 1.88 if (c == null) throw new NullPointerException();
638 jsr166 1.67 final ReentrantLock lock = this.lock;
639     lock.lock();
640     try {
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     } finally {
659     lock.unlock();
660     }
661 tim 1.1 }
662    
663     /**
664 jsr166 1.32 * Retains only the elements in this list that are contained in the
665 jsr166 1.35 * specified collection. In other words, removes from this list all of
666     * its elements that are not contained in the specified collection.
667 jsr166 1.32 *
668 jsr166 1.35 * @param c collection containing elements to be retained in this list
669 jsr166 1.92 * @return {@code true} if this list changed as a result of the call
670 jsr166 1.38 * @throws ClassCastException if the class of an element of this list
671 dl 1.73 * is incompatible with the specified collection
672 dl 1.74 * (<a href="../Collection.html#optional-restrictions">optional</a>)
673 jsr166 1.38 * @throws NullPointerException if this list contains a null element and the
674 dl 1.73 * specified collection does not permit null elements
675 dl 1.75 * (<a href="../Collection.html#optional-restrictions">optional</a>),
676 jsr166 1.38 * or if the specified collection is null
677     * @see #remove(Object)
678 tim 1.1 */
679 dl 1.42 public boolean retainAll(Collection<?> c) {
680 dl 1.88 if (c == null) throw new NullPointerException();
681 jsr166 1.67 final ReentrantLock lock = this.lock;
682     lock.lock();
683     try {
684     Object[] elements = getArray();
685     int len = elements.length;
686     if (len != 0) {
687     // temp array holds those elements we know we want to keep
688     int newlen = 0;
689     Object[] temp = new Object[len];
690     for (int i = 0; i < len; ++i) {
691     Object element = elements[i];
692     if (c.contains(element))
693     temp[newlen++] = element;
694     }
695     if (newlen != len) {
696     setArray(Arrays.copyOf(temp, newlen));
697     return true;
698     }
699     }
700     return false;
701     } finally {
702     lock.unlock();
703     }
704 tim 1.1 }
705    
706     /**
707 jsr166 1.32 * Appends all of the elements in the specified collection that
708 tim 1.1 * are not already contained in this list, to the end of
709     * this list, in the order that they are returned by the
710 jsr166 1.32 * specified collection's iterator.
711 tim 1.1 *
712 jsr166 1.36 * @param c collection containing elements to be added to this list
713 tim 1.1 * @return the number of elements added
714 jsr166 1.35 * @throws NullPointerException if the specified collection is null
715 jsr166 1.38 * @see #addIfAbsent(Object)
716 tim 1.1 */
717 dl 1.42 public int addAllAbsent(Collection<? extends E> c) {
718 jsr166 1.67 Object[] cs = c.toArray();
719     if (cs.length == 0)
720     return 0;
721     Object[] uniq = new Object[cs.length];
722     final ReentrantLock lock = this.lock;
723     lock.lock();
724     try {
725     Object[] elements = getArray();
726     int len = elements.length;
727     int added = 0;
728     for (int i = 0; i < cs.length; ++i) { // scan for duplicates
729     Object e = cs[i];
730     if (indexOf(e, elements, 0, len) < 0 &&
731     indexOf(e, uniq, 0, added) < 0)
732     uniq[added++] = e;
733     }
734     if (added > 0) {
735     Object[] newElements = Arrays.copyOf(elements, len + added);
736     System.arraycopy(uniq, 0, newElements, len, added);
737     setArray(newElements);
738     }
739     return added;
740     } finally {
741     lock.unlock();
742     }
743 tim 1.1 }
744    
745     /**
746     * Removes all of the elements from this list.
747 jsr166 1.38 * The list will be empty after this call returns.
748 tim 1.1 */
749 dl 1.42 public void clear() {
750 jsr166 1.67 final ReentrantLock lock = this.lock;
751     lock.lock();
752     try {
753     setArray(new Object[0]);
754     } finally {
755     lock.unlock();
756     }
757 tim 1.1 }
758    
759     /**
760 jsr166 1.32 * Appends all of the elements in the specified collection to the end
761     * of this list, in the order that they are returned by the specified
762     * collection's iterator.
763 tim 1.1 *
764 jsr166 1.36 * @param c collection containing elements to be added to this list
765 jsr166 1.92 * @return {@code true} if this list changed as a result of the call
766 jsr166 1.35 * @throws NullPointerException if the specified collection is null
767 jsr166 1.38 * @see #add(Object)
768 tim 1.1 */
769 dl 1.42 public boolean addAll(Collection<? extends E> c) {
770 jsr166 1.67 Object[] cs = c.toArray();
771     if (cs.length == 0)
772     return false;
773     final ReentrantLock lock = this.lock;
774     lock.lock();
775     try {
776     Object[] elements = getArray();
777     int len = elements.length;
778     Object[] newElements = Arrays.copyOf(elements, len + cs.length);
779     System.arraycopy(cs, 0, newElements, len, cs.length);
780     setArray(newElements);
781     return true;
782     } finally {
783     lock.unlock();
784     }
785 tim 1.1 }
786    
787     /**
788 jsr166 1.35 * Inserts all of the elements in the specified collection into this
789 tim 1.1 * list, starting at the specified position. Shifts the element
790     * currently at that position (if any) and any subsequent elements to
791     * the right (increases their indices). The new elements will appear
792 jsr166 1.38 * in this list in the order that they are returned by the
793     * specified collection's iterator.
794 tim 1.1 *
795 jsr166 1.35 * @param index index at which to insert the first element
796     * from the specified collection
797 jsr166 1.36 * @param c collection containing elements to be added to this list
798 jsr166 1.92 * @return {@code true} if this list changed as a result of the call
799 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
800     * @throws NullPointerException if the specified collection is null
801 jsr166 1.38 * @see #add(int,Object)
802 tim 1.1 */
803 dl 1.42 public boolean addAll(int index, Collection<? extends E> c) {
804 jsr166 1.67 Object[] cs = c.toArray();
805     final ReentrantLock lock = this.lock;
806     lock.lock();
807     try {
808     Object[] elements = getArray();
809     int len = elements.length;
810     if (index > len || index < 0)
811     throw new IndexOutOfBoundsException("Index: "+index+
812     ", Size: "+len);
813     if (cs.length == 0)
814     return false;
815     int numMoved = len - index;
816     Object[] newElements;
817     if (numMoved == 0)
818     newElements = Arrays.copyOf(elements, len + cs.length);
819     else {
820     newElements = new Object[len + cs.length];
821     System.arraycopy(elements, 0, newElements, 0, index);
822     System.arraycopy(elements, index,
823     newElements, index + cs.length,
824     numMoved);
825     }
826     System.arraycopy(cs, 0, newElements, index, cs.length);
827     setArray(newElements);
828     return true;
829     } finally {
830     lock.unlock();
831     }
832 tim 1.1 }
833    
834     /**
835 jsr166 1.87 * Saves this list to a stream (that is, serializes it).
836 tim 1.1 *
837     * @serialData The length of the array backing the list is emitted
838     * (int), followed by all of its elements (each an Object)
839     * in the proper order.
840     */
841     private void writeObject(java.io.ObjectOutputStream s)
842 jsr166 1.85 throws java.io.IOException {
843 tim 1.1
844     s.defaultWriteObject();
845    
846 dl 1.41 Object[] elements = getArray();
847 tim 1.1 // Write out array length
848 jsr166 1.71 s.writeInt(elements.length);
849 tim 1.1
850     // Write out all elements in the proper order.
851 jsr166 1.71 for (Object element : elements)
852     s.writeObject(element);
853 tim 1.1 }
854    
855     /**
856 jsr166 1.87 * Reconstitutes this list from a stream (that is, deserializes it).
857 tim 1.1 */
858 dl 1.12 private void readObject(java.io.ObjectInputStream s)
859 tim 1.1 throws java.io.IOException, ClassNotFoundException {
860    
861     s.defaultReadObject();
862    
863 dl 1.42 // bind to new lock
864     resetLock();
865    
866 tim 1.1 // Read in array length and allocate array
867 dl 1.40 int len = s.readInt();
868 dl 1.41 Object[] elements = new Object[len];
869 tim 1.1
870     // Read in all elements in the proper order.
871 dl 1.40 for (int i = 0; i < len; i++)
872 dl 1.41 elements[i] = s.readObject();
873 dl 1.40 setArray(elements);
874 tim 1.1 }
875    
876     /**
877 jsr166 1.55 * Returns a string representation of this list. The string
878     * representation consists of the string representations of the list's
879     * elements in the order they are returned by its iterator, enclosed in
880 jsr166 1.92 * square brackets ({@code "[]"}). Adjacent elements are separated by
881     * the characters {@code ", "} (comma and space). Elements are
882 jsr166 1.55 * converted to strings as by {@link String#valueOf(Object)}.
883     *
884     * @return a string representation of this list
885 tim 1.1 */
886     public String toString() {
887 jsr166 1.67 return Arrays.toString(getArray());
888 tim 1.1 }
889    
890     /**
891 jsr166 1.35 * Compares the specified object with this list for equality.
892 jsr166 1.60 * Returns {@code true} if the specified object is the same object
893     * as this object, or if it is also a {@link List} and the sequence
894     * of elements returned by an {@linkplain List#iterator() iterator}
895     * over the specified list is the same as the sequence returned by
896     * an iterator over this list. The two sequences are considered to
897     * be the same if they have the same length and corresponding
898     * elements at the same position in the sequence are <em>equal</em>.
899     * Two elements {@code e1} and {@code e2} are considered
900     * <em>equal</em> if {@code (e1==null ? e2==null : e1.equals(e2))}.
901 tim 1.1 *
902 jsr166 1.35 * @param o the object to be compared for equality with this list
903 jsr166 1.60 * @return {@code true} if the specified object is equal to this list
904 tim 1.1 */
905     public boolean equals(Object o) {
906     if (o == this)
907     return true;
908     if (!(o instanceof List))
909     return false;
910    
911 dl 1.57 List<?> list = (List<?>)(o);
912 jsr166 1.67 Iterator<?> it = list.iterator();
913     Object[] elements = getArray();
914     int len = elements.length;
915 jsr166 1.60 for (int i = 0; i < len; ++i)
916     if (!it.hasNext() || !eq(elements[i], it.next()))
917 dl 1.57 return false;
918 jsr166 1.60 if (it.hasNext())
919 tim 1.1 return false;
920     return true;
921     }
922    
923     /**
924 jsr166 1.35 * Returns the hash code value for this list.
925 dl 1.26 *
926 jsr166 1.47 * <p>This implementation uses the definition in {@link List#hashCode}.
927     *
928     * @return the hash code value for this list
929 tim 1.1 */
930     public int hashCode() {
931     int hashCode = 1;
932 jsr166 1.67 Object[] elements = getArray();
933     int len = elements.length;
934     for (int i = 0; i < len; ++i) {
935     Object obj = elements[i];
936 jsr166 1.45 hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
937 tim 1.1 }
938     return hashCode;
939     }
940    
941     /**
942 jsr166 1.35 * Returns an iterator over the elements in this list in proper sequence.
943     *
944     * <p>The returned iterator provides a snapshot of the state of the list
945     * when the iterator was constructed. No synchronization is needed while
946     * traversing the iterator. The iterator does <em>NOT</em> support the
947 jsr166 1.92 * {@code remove} method.
948 jsr166 1.35 *
949     * @return an iterator over the elements in this list in proper sequence
950 tim 1.1 */
951     public Iterator<E> iterator() {
952 dl 1.40 return new COWIterator<E>(getArray(), 0);
953 tim 1.1 }
954    
955     /**
956 jsr166 1.35 * {@inheritDoc}
957 tim 1.1 *
958 jsr166 1.35 * <p>The returned iterator provides a snapshot of the state of the list
959     * when the iterator was constructed. No synchronization is needed while
960     * traversing the iterator. The iterator does <em>NOT</em> support the
961 jsr166 1.92 * {@code remove}, {@code set} or {@code add} methods.
962 tim 1.1 */
963     public ListIterator<E> listIterator() {
964 dl 1.40 return new COWIterator<E>(getArray(), 0);
965 tim 1.1 }
966    
967     /**
968 jsr166 1.35 * {@inheritDoc}
969     *
970 jsr166 1.50 * <p>The returned iterator provides a snapshot of the state of the list
971     * when the iterator was constructed. No synchronization is needed while
972     * traversing the iterator. The iterator does <em>NOT</em> support the
973 jsr166 1.92 * {@code remove}, {@code set} or {@code add} methods.
974 jsr166 1.35 *
975     * @throws IndexOutOfBoundsException {@inheritDoc}
976 tim 1.1 */
977     public ListIterator<E> listIterator(final int index) {
978 dl 1.41 Object[] elements = getArray();
979 dl 1.40 int len = elements.length;
980 jsr166 1.45 if (index<0 || index>len)
981     throw new IndexOutOfBoundsException("Index: "+index);
982 tim 1.1
983 dl 1.48 return new COWIterator<E>(elements, index);
984 tim 1.1 }
985    
986 dl 1.98 Spliterator<E> spliterator() {
987     return Collections.arraySnapshotSpliterator
988     (getArray(), Spliterator.IMMUTABLE | Spliterator.ORDERED);
989     }
990    
991 dl 1.93 public Stream<E> stream() {
992 dl 1.98 return Streams.stream(spliterator());
993    
994 dl 1.93 }
995     public Stream<E> parallelStream() {
996 dl 1.98 return Streams.parallelStream(spliterator());
997 dl 1.93 }
998    
999     static final class COWIterator<E> implements ListIterator<E> {
1000 jsr166 1.68 /** Snapshot of the array */
1001 dl 1.41 private final Object[] snapshot;
1002 dl 1.40 /** Index of element to be returned by subsequent call to next. */
1003 tim 1.1 private int cursor;
1004    
1005 dl 1.41 private COWIterator(Object[] elements, int initialCursor) {
1006 tim 1.1 cursor = initialCursor;
1007 dl 1.40 snapshot = elements;
1008 tim 1.1 }
1009    
1010     public boolean hasNext() {
1011 dl 1.40 return cursor < snapshot.length;
1012 tim 1.1 }
1013    
1014     public boolean hasPrevious() {
1015     return cursor > 0;
1016     }
1017    
1018 jsr166 1.67 @SuppressWarnings("unchecked")
1019 tim 1.1 public E next() {
1020 jsr166 1.67 if (! hasNext())
1021 tim 1.1 throw new NoSuchElementException();
1022 jsr166 1.67 return (E) snapshot[cursor++];
1023 tim 1.1 }
1024    
1025 jsr166 1.67 @SuppressWarnings("unchecked")
1026 tim 1.1 public E previous() {
1027 jsr166 1.67 if (! hasPrevious())
1028 tim 1.1 throw new NoSuchElementException();
1029 jsr166 1.67 return (E) snapshot[--cursor];
1030 tim 1.1 }
1031    
1032     public int nextIndex() {
1033     return cursor;
1034     }
1035    
1036     public int previousIndex() {
1037 jsr166 1.45 return cursor-1;
1038 tim 1.1 }
1039    
1040     /**
1041     * Not supported. Always throws UnsupportedOperationException.
1042 jsr166 1.92 * @throws UnsupportedOperationException always; {@code remove}
1043 jsr166 1.32 * is not supported by this iterator.
1044 tim 1.1 */
1045     public void remove() {
1046     throw new UnsupportedOperationException();
1047     }
1048    
1049     /**
1050     * Not supported. Always throws UnsupportedOperationException.
1051 jsr166 1.92 * @throws UnsupportedOperationException always; {@code set}
1052 jsr166 1.32 * is not supported by this iterator.
1053 tim 1.1 */
1054 jsr166 1.33 public void set(E e) {
1055 tim 1.1 throw new UnsupportedOperationException();
1056     }
1057    
1058     /**
1059     * Not supported. Always throws UnsupportedOperationException.
1060 jsr166 1.92 * @throws UnsupportedOperationException always; {@code add}
1061 jsr166 1.32 * is not supported by this iterator.
1062 tim 1.1 */
1063 jsr166 1.33 public void add(E e) {
1064 tim 1.1 throw new UnsupportedOperationException();
1065     }
1066     }
1067    
1068     /**
1069 dl 1.40 * Returns a view of the portion of this list between
1070 jsr166 1.92 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
1071 dl 1.40 * The returned list is backed by this list, so changes in the
1072 jsr166 1.66 * returned list are reflected in this list.
1073 dl 1.40 *
1074     * <p>The semantics of the list returned by this method become
1075 jsr166 1.66 * undefined if the backing list (i.e., this list) is modified in
1076     * any way other than via the returned list.
1077 tim 1.1 *
1078 jsr166 1.35 * @param fromIndex low endpoint (inclusive) of the subList
1079     * @param toIndex high endpoint (exclusive) of the subList
1080     * @return a view of the specified range within this list
1081     * @throws IndexOutOfBoundsException {@inheritDoc}
1082 tim 1.1 */
1083 dl 1.42 public List<E> subList(int fromIndex, int toIndex) {
1084 jsr166 1.67 final ReentrantLock lock = this.lock;
1085     lock.lock();
1086     try {
1087     Object[] elements = getArray();
1088     int len = elements.length;
1089     if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
1090     throw new IndexOutOfBoundsException();
1091     return new COWSubList<E>(this, fromIndex, toIndex);
1092     } finally {
1093     lock.unlock();
1094     }
1095 tim 1.1 }
1096    
1097 dl 1.42 /**
1098     * Sublist for CopyOnWriteArrayList.
1099     * This class extends AbstractList merely for convenience, to
1100     * avoid having to define addAll, etc. This doesn't hurt, but
1101     * is wasteful. This class does not need or use modCount
1102     * mechanics in AbstractList, but does need to check for
1103     * concurrent modification using similar mechanics. On each
1104     * operation, the array that we expect the backing list to use
1105     * is checked and updated. Since we do this for all of the
1106     * base operations invoked by those defined in AbstractList,
1107     * all is well. While inefficient, this is not worth
1108     * improving. The kinds of list operations inherited from
1109     * AbstractList are already so slow on COW sublists that
1110     * adding a bit more space/time doesn't seem even noticeable.
1111     */
1112 jsr166 1.66 private static class COWSubList<E>
1113 jsr166 1.67 extends AbstractList<E>
1114     implements RandomAccess
1115 jsr166 1.66 {
1116 tim 1.1 private final CopyOnWriteArrayList<E> l;
1117     private final int offset;
1118     private int size;
1119 dl 1.41 private Object[] expectedArray;
1120 tim 1.1
1121 jsr166 1.45 // only call this holding l's lock
1122 jsr166 1.66 COWSubList(CopyOnWriteArrayList<E> list,
1123 jsr166 1.67 int fromIndex, int toIndex) {
1124 tim 1.1 l = list;
1125 dl 1.40 expectedArray = l.getArray();
1126 tim 1.1 offset = fromIndex;
1127     size = toIndex - fromIndex;
1128     }
1129    
1130     // only call this holding l's lock
1131     private void checkForComodification() {
1132 dl 1.40 if (l.getArray() != expectedArray)
1133 tim 1.1 throw new ConcurrentModificationException();
1134     }
1135    
1136     // only call this holding l's lock
1137     private void rangeCheck(int index) {
1138 jsr166 1.45 if (index<0 || index>=size)
1139     throw new IndexOutOfBoundsException("Index: "+index+
1140 jsr166 1.67 ",Size: "+size);
1141 tim 1.1 }
1142    
1143     public E set(int index, E element) {
1144 jsr166 1.67 final ReentrantLock lock = l.lock;
1145     lock.lock();
1146     try {
1147 tim 1.1 rangeCheck(index);
1148     checkForComodification();
1149 jsr166 1.45 E x = l.set(index+offset, element);
1150 dl 1.40 expectedArray = l.getArray();
1151 tim 1.1 return x;
1152 jsr166 1.67 } finally {
1153     lock.unlock();
1154     }
1155 tim 1.1 }
1156    
1157     public E get(int index) {
1158 jsr166 1.67 final ReentrantLock lock = l.lock;
1159     lock.lock();
1160     try {
1161 tim 1.1 rangeCheck(index);
1162     checkForComodification();
1163 jsr166 1.45 return l.get(index+offset);
1164 jsr166 1.67 } finally {
1165     lock.unlock();
1166     }
1167 tim 1.1 }
1168    
1169     public int size() {
1170 jsr166 1.67 final ReentrantLock lock = l.lock;
1171     lock.lock();
1172     try {
1173 tim 1.1 checkForComodification();
1174     return size;
1175 jsr166 1.67 } finally {
1176     lock.unlock();
1177     }
1178 tim 1.1 }
1179    
1180     public void add(int index, E element) {
1181 jsr166 1.67 final ReentrantLock lock = l.lock;
1182     lock.lock();
1183     try {
1184 tim 1.1 checkForComodification();
1185     if (index<0 || index>size)
1186     throw new IndexOutOfBoundsException();
1187 jsr166 1.45 l.add(index+offset, element);
1188 dl 1.40 expectedArray = l.getArray();
1189 tim 1.1 size++;
1190 jsr166 1.67 } finally {
1191     lock.unlock();
1192     }
1193 tim 1.1 }
1194    
1195 dl 1.13 public void clear() {
1196 jsr166 1.67 final ReentrantLock lock = l.lock;
1197     lock.lock();
1198     try {
1199 dl 1.13 checkForComodification();
1200     l.removeRange(offset, offset+size);
1201 dl 1.40 expectedArray = l.getArray();
1202 dl 1.13 size = 0;
1203 jsr166 1.67 } finally {
1204     lock.unlock();
1205     }
1206 dl 1.13 }
1207    
1208 tim 1.1 public E remove(int index) {
1209 jsr166 1.67 final ReentrantLock lock = l.lock;
1210     lock.lock();
1211     try {
1212 tim 1.1 rangeCheck(index);
1213     checkForComodification();
1214 jsr166 1.45 E result = l.remove(index+offset);
1215 dl 1.40 expectedArray = l.getArray();
1216 tim 1.1 size--;
1217     return result;
1218 jsr166 1.67 } finally {
1219     lock.unlock();
1220     }
1221 tim 1.1 }
1222    
1223 jsr166 1.66 public boolean remove(Object o) {
1224 jsr166 1.67 int index = indexOf(o);
1225     if (index == -1)
1226     return false;
1227     remove(index);
1228     return true;
1229 jsr166 1.66 }
1230    
1231 tim 1.1 public Iterator<E> iterator() {
1232 jsr166 1.67 final ReentrantLock lock = l.lock;
1233     lock.lock();
1234     try {
1235 tim 1.1 checkForComodification();
1236 tim 1.8 return new COWSubListIterator<E>(l, 0, offset, size);
1237 jsr166 1.67 } finally {
1238     lock.unlock();
1239     }
1240 tim 1.1 }
1241    
1242     public ListIterator<E> listIterator(final int index) {
1243 jsr166 1.67 final ReentrantLock lock = l.lock;
1244     lock.lock();
1245     try {
1246 tim 1.1 checkForComodification();
1247     if (index<0 || index>size)
1248 dl 1.40 throw new IndexOutOfBoundsException("Index: "+index+
1249 jsr166 1.67 ", Size: "+size);
1250 tim 1.8 return new COWSubListIterator<E>(l, index, offset, size);
1251 jsr166 1.67 } finally {
1252     lock.unlock();
1253     }
1254 tim 1.1 }
1255    
1256 tim 1.7 public List<E> subList(int fromIndex, int toIndex) {
1257 jsr166 1.67 final ReentrantLock lock = l.lock;
1258     lock.lock();
1259     try {
1260 tim 1.7 checkForComodification();
1261     if (fromIndex<0 || toIndex>size)
1262     throw new IndexOutOfBoundsException();
1263 dl 1.41 return new COWSubList<E>(l, fromIndex + offset,
1264 jsr166 1.67 toIndex + offset);
1265     } finally {
1266     lock.unlock();
1267     }
1268 tim 1.7 }
1269 tim 1.1
1270 dl 1.98 Spliterator<E> spliterator() {
1271 dl 1.93 int lo = offset;
1272     int hi = offset + size;
1273     Object[] a = expectedArray;
1274     if (l.getArray() != a)
1275     throw new ConcurrentModificationException();
1276     if (lo < 0 || hi > a.length)
1277     throw new IndexOutOfBoundsException();
1278 dl 1.98 return Collections.arraySnapshotSpliterator
1279     (a, lo, hi, Spliterator.IMMUTABLE | Spliterator.ORDERED);
1280     }
1281    
1282     public Stream<E> stream() {
1283     return Streams.stream(spliterator());
1284 dl 1.93 }
1285    
1286     public Stream<E> parallelStream() {
1287 dl 1.98 return Streams.parallelStream(spliterator());
1288 dl 1.93 }
1289 tim 1.7 }
1290 tim 1.1
1291 tim 1.7 private static class COWSubListIterator<E> implements ListIterator<E> {
1292 jsr166 1.80 private final ListIterator<E> it;
1293 tim 1.7 private final int offset;
1294     private final int size;
1295 jsr166 1.66
1296 jsr166 1.79 COWSubListIterator(List<E> l, int index, int offset, int size) {
1297 tim 1.7 this.offset = offset;
1298     this.size = size;
1299 jsr166 1.80 it = l.listIterator(index+offset);
1300 tim 1.7 }
1301 tim 1.1
1302 tim 1.7 public boolean hasNext() {
1303     return nextIndex() < size;
1304     }
1305 tim 1.1
1306 tim 1.7 public E next() {
1307     if (hasNext())
1308 jsr166 1.80 return it.next();
1309 tim 1.7 else
1310     throw new NoSuchElementException();
1311     }
1312 tim 1.1
1313 tim 1.7 public boolean hasPrevious() {
1314     return previousIndex() >= 0;
1315     }
1316 tim 1.1
1317 tim 1.7 public E previous() {
1318     if (hasPrevious())
1319 jsr166 1.80 return it.previous();
1320 tim 1.7 else
1321     throw new NoSuchElementException();
1322     }
1323 tim 1.1
1324 tim 1.7 public int nextIndex() {
1325 jsr166 1.80 return it.nextIndex() - offset;
1326 tim 1.7 }
1327 tim 1.1
1328 tim 1.7 public int previousIndex() {
1329 jsr166 1.80 return it.previousIndex() - offset;
1330 tim 1.1 }
1331    
1332 tim 1.7 public void remove() {
1333     throw new UnsupportedOperationException();
1334     }
1335 tim 1.1
1336 jsr166 1.33 public void set(E e) {
1337 tim 1.7 throw new UnsupportedOperationException();
1338 tim 1.1 }
1339    
1340 jsr166 1.33 public void add(E e) {
1341 tim 1.7 throw new UnsupportedOperationException();
1342     }
1343 tim 1.1 }
1344    
1345 dl 1.42 // Support for resetting lock while deserializing
1346 dl 1.72 private void resetLock() {
1347     UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock());
1348     }
1349     private static final sun.misc.Unsafe UNSAFE;
1350 dl 1.42 private static final long lockOffset;
1351     static {
1352     try {
1353 dl 1.72 UNSAFE = sun.misc.Unsafe.getUnsafe();
1354 jsr166 1.76 Class<?> k = CopyOnWriteArrayList.class;
1355 dl 1.72 lockOffset = UNSAFE.objectFieldOffset
1356     (k.getDeclaredField("lock"));
1357     } catch (Exception e) {
1358     throw new Error(e);
1359     }
1360 dl 1.42 }
1361 tim 1.1 }