2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
27 * Written by Doug Lea with assistance from members of JCP JSR-166
28 * Expert Group. Adapted and released, under explicit permission,
29 * from JDK ArrayList.java which carries the following copyright:
31 * Copyright 1997 by Sun Microsystems, Inc.,
32 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
33 * All rights reserved.
36 package java.util.concurrent;
38 import java.util.concurrent.locks.*;
41 * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
42 * operations (<tt>add</tt>, <tt>set</tt>, and so on) are implemented by
43 * making a fresh copy of the underlying array.
45 * <p> This is ordinarily too costly, but may be <em>more</em> efficient
46 * than alternatives when traversal operations vastly outnumber
47 * mutations, and is useful when you cannot or don't want to
48 * synchronize traversals, yet need to preclude interference among
49 * concurrent threads. The "snapshot" style iterator method uses a
50 * reference to the state of the array at the point that the iterator
51 * was created. This array never changes during the lifetime of the
52 * iterator, so interference is impossible and the iterator is
53 * guaranteed not to throw <tt>ConcurrentModificationException</tt>.
54 * The iterator will not reflect additions, removals, or changes to
55 * the list since the iterator was created. Element-changing
56 * operations on iterators themselves (<tt>remove</tt>, <tt>set</tt>, and
57 * <tt>add</tt>) are not supported. These methods throw
58 * <tt>UnsupportedOperationException</tt>.
60 * <p>All elements are permitted, including <tt>null</tt>.
62 * <p>Memory consistency effects: As with other concurrent
63 * collections, actions in a thread prior to placing an object into a
64 * {@code CopyOnWriteArrayList}
65 * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
66 * actions subsequent to the access or removal of that element from
67 * the {@code CopyOnWriteArrayList} in another thread.
69 * <p>This class is a member of the
70 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
71 * Java Collections Framework</a>.
75 * @param <E> the type of elements held in this collection
77 public class CopyOnWriteArrayList<E>
78 implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
79 private static final long serialVersionUID = 8673264195747942595L;
81 /** The lock protecting all mutators */
82 transient ReentrantLock lock = new ReentrantLock();
84 /** The array, accessed only via getArray/setArray. */
85 private volatile transient Object[] array;
88 * Gets the array. Non-private so as to also be accessible
89 * from CopyOnWriteArraySet class.
91 final Object[] getArray() {
98 final void setArray(Object[] a) {
103 * Creates an empty list.
105 public CopyOnWriteArrayList() {
106 setArray(new Object[0]);
110 * Creates a list containing the elements of the specified
111 * collection, in the order they are returned by the collection's
114 * @param c the collection of initially held elements
115 * @throws NullPointerException if the specified collection is null
117 public CopyOnWriteArrayList(Collection<? extends E> c) {
118 Object[] elements = c.toArray();
119 // c.toArray might (incorrectly) not return Object[] (see 6260652)
120 if (elements.getClass() != Object[].class)
121 elements = Arrays.copyOf(elements, elements.length, Object[].class);
126 * Creates a list holding a copy of the given array.
128 * @param toCopyIn the array (a copy of this array is used as the
130 * @throws NullPointerException if the specified array is null
132 public CopyOnWriteArrayList(E[] toCopyIn) {
133 setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
137 * Returns the number of elements in this list.
139 * @return the number of elements in this list
142 return getArray().length;
146 * Returns <tt>true</tt> if this list contains no elements.
148 * @return <tt>true</tt> if this list contains no elements
150 public boolean isEmpty() {
155 * Test for equality, coping with nulls.
157 private static boolean eq(Object o1, Object o2) {
158 return (o1 == null ? o2 == null : o1.equals(o2));
162 * static version of indexOf, to allow repeated calls without
163 * needing to re-acquire array each time.
164 * @param o element to search for
165 * @param elements the array
166 * @param index first index to search
167 * @param fence one past last index to search
168 * @return index of element, or -1 if absent
170 private static int indexOf(Object o, Object[] elements,
171 int index, int fence) {
173 for (int i = index; i < fence; i++)
174 if (elements[i] == null)
177 for (int i = index; i < fence; i++)
178 if (o.equals(elements[i]))
185 * static version of lastIndexOf.
186 * @param o element to search for
187 * @param elements the array
188 * @param index first index to search
189 * @return index of element, or -1 if absent
191 private static int lastIndexOf(Object o, Object[] elements, int index) {
193 for (int i = index; i >= 0; i--)
194 if (elements[i] == null)
197 for (int i = index; i >= 0; i--)
198 if (o.equals(elements[i]))
205 * Returns <tt>true</tt> if this list contains the specified element.
206 * More formally, returns <tt>true</tt> if and only if this list contains
207 * at least one element <tt>e</tt> such that
208 * <tt>(o==null ? e==null : o.equals(e))</tt>.
210 * @param o element whose presence in this list is to be tested
211 * @return <tt>true</tt> if this list contains the specified element
213 public boolean contains(Object o) {
214 Object[] elements = getArray();
215 return indexOf(o, elements, 0, elements.length) >= 0;
221 public int indexOf(Object o) {
222 Object[] elements = getArray();
223 return indexOf(o, elements, 0, elements.length);
227 * Returns the index of the first occurrence of the specified element in
228 * this list, searching forwards from <tt>index</tt>, or returns -1 if
229 * the element is not found.
230 * More formally, returns the lowest index <tt>i</tt> such that
231 * <tt>(i >= index && (e==null ? get(i)==null : e.equals(get(i))))</tt>,
232 * or -1 if there is no such index.
234 * @param e element to search for
235 * @param index index to start searching from
236 * @return the index of the first occurrence of the element in
237 * this list at position <tt>index</tt> or later in the list;
238 * <tt>-1</tt> if the element is not found.
239 * @throws IndexOutOfBoundsException if the specified index is negative
241 public int indexOf(E e, int index) {
242 Object[] elements = getArray();
243 return indexOf(e, elements, index, elements.length);
249 public int lastIndexOf(Object o) {
250 Object[] elements = getArray();
251 return lastIndexOf(o, elements, elements.length - 1);
255 * Returns the index of the last occurrence of the specified element in
256 * this list, searching backwards from <tt>index</tt>, or returns -1 if
257 * the element is not found.
258 * More formally, returns the highest index <tt>i</tt> such that
259 * <tt>(i <= index && (e==null ? get(i)==null : e.equals(get(i))))</tt>,
260 * or -1 if there is no such index.
262 * @param e element to search for
263 * @param index index to start searching backwards from
264 * @return the index of the last occurrence of the element at position
265 * less than or equal to <tt>index</tt> in this list;
266 * -1 if the element is not found.
267 * @throws IndexOutOfBoundsException if the specified index is greater
268 * than or equal to the current size of this list
270 public int lastIndexOf(E e, int index) {
271 Object[] elements = getArray();
272 return lastIndexOf(e, elements, index);
276 * Returns a shallow copy of this list. (The elements themselves
279 * @return a clone of this list
281 public Object clone() {
283 CopyOnWriteArrayList c = (CopyOnWriteArrayList)(super.clone());
286 } catch (CloneNotSupportedException e) {
287 // this shouldn't happen, since we are Cloneable
288 throw new InternalError();
293 * Returns an array containing all of the elements in this list
294 * in proper sequence (from first to last element).
296 * <p>The returned array will be "safe" in that no references to it are
297 * maintained by this list. (In other words, this method must allocate
298 * a new array). The caller is thus free to modify the returned array.
300 * <p>This method acts as bridge between array-based and collection-based
303 * @return an array containing all the elements in this list
305 public Object[] toArray() {
306 Object[] elements = getArray();
307 return Arrays.copyOf(elements, elements.length);
311 * Returns an array containing all of the elements in this list in
312 * proper sequence (from first to last element); the runtime type of
313 * the returned array is that of the specified array. If the list fits
314 * in the specified array, it is returned therein. Otherwise, a new
315 * array is allocated with the runtime type of the specified array and
316 * the size of this list.
318 * <p>If this list fits in the specified array with room to spare
319 * (i.e., the array has more elements than this list), the element in
320 * the array immediately following the end of the list is set to
321 * <tt>null</tt>. (This is useful in determining the length of this
322 * list <i>only</i> if the caller knows that this list does not contain
323 * any null elements.)
325 * <p>Like the {@link #toArray()} method, this method acts as bridge between
326 * array-based and collection-based APIs. Further, this method allows
327 * precise control over the runtime type of the output array, and may,
328 * under certain circumstances, be used to save allocation costs.
330 * <p>Suppose <tt>x</tt> is a list known to contain only strings.
331 * The following code can be used to dump the list into a newly
332 * allocated array of <tt>String</tt>:
335 * String[] y = x.toArray(new String[0]);</pre>
337 * Note that <tt>toArray(new Object[0])</tt> is identical in function to
338 * <tt>toArray()</tt>.
340 * @param a the array into which the elements of the list are to
341 * be stored, if it is big enough; otherwise, a new array of the
342 * same runtime type is allocated for this purpose.
343 * @return an array containing all the elements in this list
344 * @throws ArrayStoreException if the runtime type of the specified array
345 * is not a supertype of the runtime type of every element in
347 * @throws NullPointerException if the specified array is null
349 @SuppressWarnings("unchecked")
350 public <T> T[] toArray(T a[]) {
351 Object[] elements = getArray();
352 int len = elements.length;
354 return (T[]) Arrays.copyOf(elements, len, a.getClass());
356 System.arraycopy(elements, 0, a, 0, len);
363 // Positional Access Operations
365 @SuppressWarnings("unchecked")
366 private E get(Object[] a, int index) {
373 * @throws IndexOutOfBoundsException {@inheritDoc}
375 public E get(int index) {
376 return get(getArray(), index);
380 * Replaces the element at the specified position in this list with the
383 * @throws IndexOutOfBoundsException {@inheritDoc}
385 public E set(int index, E element) {
386 final ReentrantLock lock = this.lock;
389 Object[] elements = getArray();
390 E oldValue = get(elements, index);
392 if (oldValue != element) {
393 int len = elements.length;
394 Object[] newElements = Arrays.copyOf(elements, len);
395 newElements[index] = element;
396 setArray(newElements);
398 // Not quite a no-op; ensures volatile write semantics
408 * Appends the specified element to the end of this list.
410 * @param e element to be appended to this list
411 * @return <tt>true</tt> (as specified by {@link Collection#add})
413 public boolean add(E e) {
414 final ReentrantLock lock = this.lock;
417 Object[] elements = getArray();
418 int len = elements.length;
419 Object[] newElements = Arrays.copyOf(elements, len + 1);
420 newElements[len] = e;
421 setArray(newElements);
429 * Inserts the specified element at the specified position in this
430 * list. Shifts the element currently at that position (if any) and
431 * any subsequent elements to the right (adds one to their indices).
433 * @throws IndexOutOfBoundsException {@inheritDoc}
435 public void add(int index, E element) {
436 final ReentrantLock lock = this.lock;
439 Object[] elements = getArray();
440 int len = elements.length;
441 if (index > len || index < 0)
442 throw new IndexOutOfBoundsException("Index: "+index+
444 Object[] newElements;
445 int numMoved = len - index;
447 newElements = Arrays.copyOf(elements, len + 1);
449 newElements = new Object[len + 1];
450 System.arraycopy(elements, 0, newElements, 0, index);
451 System.arraycopy(elements, index, newElements, index + 1,
454 newElements[index] = element;
455 setArray(newElements);
462 * Removes the element at the specified position in this list.
463 * Shifts any subsequent elements to the left (subtracts one from their
464 * indices). Returns the element that was removed from the list.
466 * @throws IndexOutOfBoundsException {@inheritDoc}
468 public E remove(int index) {
469 final ReentrantLock lock = this.lock;
472 Object[] elements = getArray();
473 int len = elements.length;
474 E oldValue = get(elements, index);
475 int numMoved = len - index - 1;
477 setArray(Arrays.copyOf(elements, len - 1));
479 Object[] newElements = new Object[len - 1];
480 System.arraycopy(elements, 0, newElements, 0, index);
481 System.arraycopy(elements, index + 1, newElements, index,
483 setArray(newElements);
492 * Removes the first occurrence of the specified element from this list,
493 * if it is present. If this list does not contain the element, it is
494 * unchanged. More formally, removes the element with the lowest index
495 * <tt>i</tt> such that
496 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
497 * (if such an element exists). Returns <tt>true</tt> if this list
498 * contained the specified element (or equivalently, if this list
499 * changed as a result of the call).
501 * @param o element to be removed from this list, if present
502 * @return <tt>true</tt> if this list contained the specified element
504 public boolean remove(Object o) {
505 final ReentrantLock lock = this.lock;
508 Object[] elements = getArray();
509 int len = elements.length;
511 // Copy while searching for element to remove
512 // This wins in the normal case of element being present
513 int newlen = len - 1;
514 Object[] newElements = new Object[newlen];
516 for (int i = 0; i < newlen; ++i) {
517 if (eq(o, elements[i])) {
518 // found one; copy remaining and exit
519 for (int k = i + 1; k < len; ++k)
520 newElements[k-1] = elements[k];
521 setArray(newElements);
524 newElements[i] = elements[i];
527 // special handling for last cell
528 if (eq(o, elements[newlen])) {
529 setArray(newElements);
540 * Removes from this list all of the elements whose index is between
541 * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
542 * Shifts any succeeding elements to the left (reduces their index).
543 * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
544 * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
546 * @param fromIndex index of first element to be removed
547 * @param toIndex index after last element to be removed
548 * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range
549 * ({@code{fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
551 private void removeRange(int fromIndex, int toIndex) {
552 final ReentrantLock lock = this.lock;
555 Object[] elements = getArray();
556 int len = elements.length;
558 if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
559 throw new IndexOutOfBoundsException();
560 int newlen = len - (toIndex - fromIndex);
561 int numMoved = len - toIndex;
563 setArray(Arrays.copyOf(elements, newlen));
565 Object[] newElements = new Object[newlen];
566 System.arraycopy(elements, 0, newElements, 0, fromIndex);
567 System.arraycopy(elements, toIndex, newElements,
568 fromIndex, numMoved);
569 setArray(newElements);
577 * Append the element if not present.
579 * @param e element to be added to this list, if absent
580 * @return <tt>true</tt> if the element was added
582 public boolean addIfAbsent(E e) {
583 final ReentrantLock lock = this.lock;
586 // Copy while checking if already present.
587 // This wins in the most common case where it is not present
588 Object[] elements = getArray();
589 int len = elements.length;
590 Object[] newElements = new Object[len + 1];
591 for (int i = 0; i < len; ++i) {
592 if (eq(e, elements[i]))
593 return false; // exit, throwing away copy
595 newElements[i] = elements[i];
597 newElements[len] = e;
598 setArray(newElements);
606 * Returns <tt>true</tt> if this list contains all of the elements of the
607 * specified collection.
609 * @param c collection to be checked for containment in this list
610 * @return <tt>true</tt> if this list contains all of the elements of the
611 * specified collection
612 * @throws NullPointerException if the specified collection is null
613 * @see #contains(Object)
615 public boolean containsAll(Collection<?> c) {
616 Object[] elements = getArray();
617 int len = elements.length;
619 if (indexOf(e, elements, 0, len) < 0)
626 * Removes from this list all of its elements that are contained in
627 * the specified collection. This is a particularly expensive operation
628 * in this class because of the need for an internal temporary array.
630 * @param c collection containing elements to be removed from this list
631 * @return <tt>true</tt> if this list changed as a result of the call
632 * @throws ClassCastException if the class of an element of this list
633 * is incompatible with the specified collection
634 * (<a href="../Collection.html#optional-restrictions">optional</a>)
635 * @throws NullPointerException if this list contains a null element and the
636 * specified collection does not permit null elements
637 * (<a href="../Collection.html#optional-restrictions">optional</a>),
638 * or if the specified collection is null
639 * @see #remove(Object)
641 public boolean removeAll(Collection<?> c) {
642 final ReentrantLock lock = this.lock;
645 Object[] elements = getArray();
646 int len = elements.length;
648 // temp array holds those elements we know we want to keep
650 Object[] temp = new Object[len];
651 for (int i = 0; i < len; ++i) {
652 Object element = elements[i];
653 if (!c.contains(element))
654 temp[newlen++] = element;
657 setArray(Arrays.copyOf(temp, newlen));
668 * Retains only the elements in this list that are contained in the
669 * specified collection. In other words, removes from this list all of
670 * its elements that are not contained in the specified collection.
672 * @param c collection containing elements to be retained in this list
673 * @return <tt>true</tt> if this list changed as a result of the call
674 * @throws ClassCastException if the class of an element of this list
675 * is incompatible with the specified collection
676 * (<a href="../Collection.html#optional-restrictions">optional</a>)
677 * @throws NullPointerException if this list contains a null element and the
678 * specified collection does not permit null elements
679 * (<a href="../Collection.html#optional-restrictions">optional</a>),
680 * or if the specified collection is null
681 * @see #remove(Object)
683 public boolean retainAll(Collection<?> c) {
684 final ReentrantLock lock = this.lock;
687 Object[] elements = getArray();
688 int len = elements.length;
690 // temp array holds those elements we know we want to keep
692 Object[] temp = new Object[len];
693 for (int i = 0; i < len; ++i) {
694 Object element = elements[i];
695 if (c.contains(element))
696 temp[newlen++] = element;
699 setArray(Arrays.copyOf(temp, newlen));
710 * Appends all of the elements in the specified collection that
711 * are not already contained in this list, to the end of
712 * this list, in the order that they are returned by the
713 * specified collection's iterator.
715 * @param c collection containing elements to be added to this list
716 * @return the number of elements added
717 * @throws NullPointerException if the specified collection is null
718 * @see #addIfAbsent(Object)
720 public int addAllAbsent(Collection<? extends E> c) {
721 Object[] cs = c.toArray();
724 Object[] uniq = new Object[cs.length];
725 final ReentrantLock lock = this.lock;
728 Object[] elements = getArray();
729 int len = elements.length;
731 for (int i = 0; i < cs.length; ++i) { // scan for duplicates
733 if (indexOf(e, elements, 0, len) < 0 &&
734 indexOf(e, uniq, 0, added) < 0)
738 Object[] newElements = Arrays.copyOf(elements, len + added);
739 System.arraycopy(uniq, 0, newElements, len, added);
740 setArray(newElements);
749 * Removes all of the elements from this list.
750 * The list will be empty after this call returns.
752 public void clear() {
753 final ReentrantLock lock = this.lock;
756 setArray(new Object[0]);
763 * Appends all of the elements in the specified collection to the end
764 * of this list, in the order that they are returned by the specified
765 * collection's iterator.
767 * @param c collection containing elements to be added to this list
768 * @return <tt>true</tt> if this list changed as a result of the call
769 * @throws NullPointerException if the specified collection is null
772 public boolean addAll(Collection<? extends E> c) {
773 Object[] cs = c.toArray();
776 final ReentrantLock lock = this.lock;
779 Object[] elements = getArray();
780 int len = elements.length;
781 Object[] newElements = Arrays.copyOf(elements, len + cs.length);
782 System.arraycopy(cs, 0, newElements, len, cs.length);
783 setArray(newElements);
791 * Inserts all of the elements in the specified collection into this
792 * list, starting at the specified position. Shifts the element
793 * currently at that position (if any) and any subsequent elements to
794 * the right (increases their indices). The new elements will appear
795 * in this list in the order that they are returned by the
796 * specified collection's iterator.
798 * @param index index at which to insert the first element
799 * from the specified collection
800 * @param c collection containing elements to be added to this list
801 * @return <tt>true</tt> if this list changed as a result of the call
802 * @throws IndexOutOfBoundsException {@inheritDoc}
803 * @throws NullPointerException if the specified collection is null
804 * @see #add(int,Object)
806 public boolean addAll(int index, Collection<? extends E> c) {
807 Object[] cs = c.toArray();
808 final ReentrantLock lock = this.lock;
811 Object[] elements = getArray();
812 int len = elements.length;
813 if (index > len || index < 0)
814 throw new IndexOutOfBoundsException("Index: "+index+
818 int numMoved = len - index;
819 Object[] newElements;
821 newElements = Arrays.copyOf(elements, len + cs.length);
823 newElements = new Object[len + cs.length];
824 System.arraycopy(elements, 0, newElements, 0, index);
825 System.arraycopy(elements, index,
826 newElements, index + cs.length,
829 System.arraycopy(cs, 0, newElements, index, cs.length);
830 setArray(newElements);
838 * Saves the state of the list to a stream (that is, serializes it).
840 * @serialData The length of the array backing the list is emitted
841 * (int), followed by all of its elements (each an Object)
842 * in the proper order.
843 * @param s the stream
845 private void writeObject(java.io.ObjectOutputStream s)
846 throws java.io.IOException{
848 s.defaultWriteObject();
850 Object[] elements = getArray();
851 // Write out array length
852 s.writeInt(elements.length);
854 // Write out all elements in the proper order.
855 for (Object element : elements)
856 s.writeObject(element);
860 * Reconstitutes the list from a stream (that is, deserializes it).
862 * @param s the stream
864 private void readObject(java.io.ObjectInputStream s)
865 throws java.io.IOException, ClassNotFoundException {
867 s.defaultReadObject();
872 // Read in array length and allocate array
873 int len = s.readInt();
874 Object[] elements = new Object[len];
876 // Read in all elements in the proper order.
877 for (int i = 0; i < len; i++)
878 elements[i] = s.readObject();
883 * Returns a string representation of this list. The string
884 * representation consists of the string representations of the list's
885 * elements in the order they are returned by its iterator, enclosed in
886 * square brackets (<tt>"[]"</tt>). Adjacent elements are separated by
887 * the characters <tt>", "</tt> (comma and space). Elements are
888 * converted to strings as by {@link String#valueOf(Object)}.
890 * @return a string representation of this list
892 public String toString() {
893 return Arrays.toString(getArray());
897 * Compares the specified object with this list for equality.
898 * Returns {@code true} if the specified object is the same object
899 * as this object, or if it is also a {@link List} and the sequence
900 * of elements returned by an {@linkplain List#iterator() iterator}
901 * over the specified list is the same as the sequence returned by
902 * an iterator over this list. The two sequences are considered to
903 * be the same if they have the same length and corresponding
904 * elements at the same position in the sequence are <em>equal</em>.
905 * Two elements {@code e1} and {@code e2} are considered
906 * <em>equal</em> if {@code (e1==null ? e2==null : e1.equals(e2))}.
908 * @param o the object to be compared for equality with this list
909 * @return {@code true} if the specified object is equal to this list
911 public boolean equals(Object o) {
914 if (!(o instanceof List))
917 List<?> list = (List<?>)(o);
918 Iterator<?> it = list.iterator();
919 Object[] elements = getArray();
920 int len = elements.length;
921 for (int i = 0; i < len; ++i)
922 if (!it.hasNext() || !eq(elements[i], it.next()))
930 * Returns the hash code value for this list.
932 * <p>This implementation uses the definition in {@link List#hashCode}.
934 * @return the hash code value for this list
936 public int hashCode() {
938 Object[] elements = getArray();
939 int len = elements.length;
940 for (int i = 0; i < len; ++i) {
941 Object obj = elements[i];
942 hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
948 * Returns an iterator over the elements in this list in proper sequence.
950 * <p>The returned iterator provides a snapshot of the state of the list
951 * when the iterator was constructed. No synchronization is needed while
952 * traversing the iterator. The iterator does <em>NOT</em> support the
953 * <tt>remove</tt> method.
955 * @return an iterator over the elements in this list in proper sequence
957 public Iterator<E> iterator() {
958 return new COWIterator<E>(getArray(), 0);
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 * <tt>remove</tt>, <tt>set</tt> or <tt>add</tt> methods.
969 public ListIterator<E> listIterator() {
970 return new COWIterator<E>(getArray(), 0);
976 * <p>The returned iterator provides a snapshot of the state of the list
977 * when the iterator was constructed. No synchronization is needed while
978 * traversing the iterator. The iterator does <em>NOT</em> support the
979 * <tt>remove</tt>, <tt>set</tt> or <tt>add</tt> methods.
981 * @throws IndexOutOfBoundsException {@inheritDoc}
983 public ListIterator<E> listIterator(final int index) {
984 Object[] elements = getArray();
985 int len = elements.length;
986 if (index<0 || index>len)
987 throw new IndexOutOfBoundsException("Index: "+index);
989 return new COWIterator<E>(elements, index);
992 private static class COWIterator<E> implements ListIterator<E> {
993 /** Snapshot of the array */
994 private final Object[] snapshot;
995 /** Index of element to be returned by subsequent call to next. */
998 private COWIterator(Object[] elements, int initialCursor) {
999 cursor = initialCursor;
1000 snapshot = elements;
1003 public boolean hasNext() {
1004 return cursor < snapshot.length;
1007 public boolean hasPrevious() {
1011 @SuppressWarnings("unchecked")
1014 throw new NoSuchElementException();
1015 return (E) snapshot[cursor++];
1018 @SuppressWarnings("unchecked")
1019 public E previous() {
1020 if (! hasPrevious())
1021 throw new NoSuchElementException();
1022 return (E) snapshot[--cursor];
1025 public int nextIndex() {
1029 public int previousIndex() {
1034 * Not supported. Always throws UnsupportedOperationException.
1035 * @throws UnsupportedOperationException always; <tt>remove</tt>
1036 * is not supported by this iterator.
1038 public void remove() {
1039 throw new UnsupportedOperationException();
1043 * Not supported. Always throws UnsupportedOperationException.
1044 * @throws UnsupportedOperationException always; <tt>set</tt>
1045 * is not supported by this iterator.
1047 public void set(E e) {
1048 throw new UnsupportedOperationException();
1052 * Not supported. Always throws UnsupportedOperationException.
1053 * @throws UnsupportedOperationException always; <tt>add</tt>
1054 * is not supported by this iterator.
1056 public void add(E e) {
1057 throw new UnsupportedOperationException();
1062 * Returns a view of the portion of this list between
1063 * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
1064 * The returned list is backed by this list, so changes in the
1065 * returned list are reflected in this list.
1067 * <p>The semantics of the list returned by this method become
1068 * undefined if the backing list (i.e., this list) is modified in
1069 * any way other than via the returned list.
1071 * @param fromIndex low endpoint (inclusive) of the subList
1072 * @param toIndex high endpoint (exclusive) of the subList
1073 * @return a view of the specified range within this list
1074 * @throws IndexOutOfBoundsException {@inheritDoc}
1076 public List<E> subList(int fromIndex, int toIndex) {
1077 final ReentrantLock lock = this.lock;
1080 Object[] elements = getArray();
1081 int len = elements.length;
1082 if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
1083 throw new IndexOutOfBoundsException();
1084 return new COWSubList<E>(this, fromIndex, toIndex);
1091 * Sublist for CopyOnWriteArrayList.
1092 * This class extends AbstractList merely for convenience, to
1093 * avoid having to define addAll, etc. This doesn't hurt, but
1094 * is wasteful. This class does not need or use modCount
1095 * mechanics in AbstractList, but does need to check for
1096 * concurrent modification using similar mechanics. On each
1097 * operation, the array that we expect the backing list to use
1098 * is checked and updated. Since we do this for all of the
1099 * base operations invoked by those defined in AbstractList,
1100 * all is well. While inefficient, this is not worth
1101 * improving. The kinds of list operations inherited from
1102 * AbstractList are already so slow on COW sublists that
1103 * adding a bit more space/time doesn't seem even noticeable.
1105 private static class COWSubList<E>
1106 extends AbstractList<E>
1107 implements RandomAccess
1109 private final CopyOnWriteArrayList<E> l;
1110 private final int offset;
1112 private Object[] expectedArray;
1114 // only call this holding l's lock
1115 COWSubList(CopyOnWriteArrayList<E> list,
1116 int fromIndex, int toIndex) {
1118 expectedArray = l.getArray();
1120 size = toIndex - fromIndex;
1123 // only call this holding l's lock
1124 private void checkForComodification() {
1125 if (l.getArray() != expectedArray)
1126 throw new ConcurrentModificationException();
1129 // only call this holding l's lock
1130 private void rangeCheck(int index) {
1131 if (index<0 || index>=size)
1132 throw new IndexOutOfBoundsException("Index: "+index+
1136 public E set(int index, E element) {
1137 final ReentrantLock lock = l.lock;
1141 checkForComodification();
1142 E x = l.set(index+offset, element);
1143 expectedArray = l.getArray();
1150 public E get(int index) {
1151 final ReentrantLock lock = l.lock;
1155 checkForComodification();
1156 return l.get(index+offset);
1163 final ReentrantLock lock = l.lock;
1166 checkForComodification();
1173 public void add(int index, E element) {
1174 final ReentrantLock lock = l.lock;
1177 checkForComodification();
1178 if (index<0 || index>size)
1179 throw new IndexOutOfBoundsException();
1180 l.add(index+offset, element);
1181 expectedArray = l.getArray();
1188 public void clear() {
1189 final ReentrantLock lock = l.lock;
1192 checkForComodification();
1193 l.removeRange(offset, offset+size);
1194 expectedArray = l.getArray();
1201 public E remove(int index) {
1202 final ReentrantLock lock = l.lock;
1206 checkForComodification();
1207 E result = l.remove(index+offset);
1208 expectedArray = l.getArray();
1216 public boolean remove(Object o) {
1217 int index = indexOf(o);
1224 public Iterator<E> iterator() {
1225 final ReentrantLock lock = l.lock;
1228 checkForComodification();
1229 return new COWSubListIterator<E>(l, 0, offset, size);
1235 public ListIterator<E> listIterator(final int index) {
1236 final ReentrantLock lock = l.lock;
1239 checkForComodification();
1240 if (index<0 || index>size)
1241 throw new IndexOutOfBoundsException("Index: "+index+
1243 return new COWSubListIterator<E>(l, index, offset, size);
1249 public List<E> subList(int fromIndex, int toIndex) {
1250 final ReentrantLock lock = l.lock;
1253 checkForComodification();
1254 if (fromIndex<0 || toIndex>size)
1255 throw new IndexOutOfBoundsException();
1256 return new COWSubList<E>(l, fromIndex + offset,
1266 private static class COWSubListIterator<E> implements ListIterator<E> {
1267 private final ListIterator<E> i;
1268 private final int index;
1269 private final int offset;
1270 private final int size;
1272 COWSubListIterator(List<E> l, int index, int offset,
1275 this.offset = offset;
1277 i = l.listIterator(index+offset);
1280 public boolean hasNext() {
1281 return nextIndex() < size;
1288 throw new NoSuchElementException();
1291 public boolean hasPrevious() {
1292 return previousIndex() >= 0;
1295 public E previous() {
1297 return i.previous();
1299 throw new NoSuchElementException();
1302 public int nextIndex() {
1303 return i.nextIndex() - offset;
1306 public int previousIndex() {
1307 return i.previousIndex() - offset;
1310 public void remove() {
1311 throw new UnsupportedOperationException();
1314 public void set(E e) {
1315 throw new UnsupportedOperationException();
1318 public void add(E e) {
1319 throw new UnsupportedOperationException();
1323 // Support for resetting lock while deserializing
1324 private void resetLock() {
1325 this.lock = new ReentrantLock();