ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.24
Committed: Tue Jan 27 11:36:31 2004 UTC (20 years, 4 months ago) by dl
Branch: MAIN
Changes since 1.23: +5 -0 lines
Log Message:
Add Collection framework membership doc

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     import java.util.*;
19    
20     /**
21 dl 1.4 * A variant of {@link java.util.ArrayList} in which all mutative
22     * operations (add, set, and so on) are implemented by making a fresh
23     * copy of the underlying array. <p>
24 tim 1.1 *
25 dl 1.12 * This is ordinarily too costly, but may be <em>more</em> efficient
26     * than alternatives when traversal operations vastly outnumber
27     * mutations, and is useful when you cannot or don't want to
28     * synchronize traversals, yet need to preclude interference among
29 dl 1.15 * concurrent threads. The "snapshot" style iterator method uses a
30     * reference to the state of the array at the point that the iterator
31     * was created. This array never changes during the lifetime of the
32     * iterator, so interference is impossible and the iterator is
33     * guaranteed not to throw <tt>ConcurrentModificationException</tt>.
34     * The iterator will not reflect additions, removals, or changes to
35     * the list since the iterator was created. Element-changing
36     * operations on iterators themselves (remove, set, and add) are not
37     * supported. These methods throw
38     * <tt>UnsupportedOperationException</tt>.
39 dl 1.24 *
40     * <p>This class is a member of the
41     * <a href="{@docRoot}/../guide/collections/index.html">
42     * Java Collections Framework</a>.
43     *
44 dl 1.6 * @since 1.5
45     * @author Doug Lea
46 dl 1.19 * @param <E> the type of elements held in this collection
47 dl 1.6 */
48 tim 1.1 public class CopyOnWriteArrayList<E>
49     implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
50 dl 1.11 private static final long serialVersionUID = 8673264195747942595L;
51 tim 1.1
52     /**
53 dl 1.6 * The held array. Directly accessed only within synchronized
54 tim 1.1 * methods
55     */
56 dl 1.12 private volatile transient E[] array;
57 tim 1.1
58     /**
59     * Accessor to the array intended to be called from
60     * within unsynchronized read-only methods
61     **/
62 dl 1.12 private E[] array() { return array; }
63 tim 1.1
64     /**
65 dl 1.15 * Creates an empty list.
66 tim 1.1 */
67     public CopyOnWriteArrayList() {
68 dl 1.12 array = (E[]) new Object[0];
69 tim 1.1 }
70    
71     /**
72 dl 1.15 * Creates a list containing the elements of the specified
73 tim 1.1 * Collection, in the order they are returned by the Collection's
74     * iterator.
75 dl 1.6 * @param c the collection of initially held elements
76 tim 1.1 */
77 tim 1.22 public CopyOnWriteArrayList(Collection<? extends E> c) {
78 dl 1.12 array = (E[]) new Object[c.size()];
79 tim 1.22 Iterator<? extends E> i = c.iterator();
80 tim 1.1 int size = 0;
81     while (i.hasNext())
82 dl 1.12 array[size++] = i.next();
83 tim 1.1 }
84    
85     /**
86 tim 1.9 * Create a new CopyOnWriteArrayList holding a copy of given array.
87     *
88     * @param toCopyIn the array (a copy of this array is used as the
89     * internal array)
90 tim 1.1 **/
91     public CopyOnWriteArrayList(E[] toCopyIn) {
92     copyIn(toCopyIn, 0, toCopyIn.length);
93     }
94    
95     /**
96 dl 1.14 * Replace the held array with a copy of the <tt>n</tt>
97 dl 1.12 * elements of the provided array, starting at position
98 dl 1.14 * <tt>first</tt>. To copy an entire array, call with
99 dl 1.12 * arguments (array, 0, array.length).
100 tim 1.1 * @param toCopyIn the array. A copy of the indicated elements of
101     * this array is used as the
102     * internal array.
103     * @param first The index of first position of the array to
104     * start copying from.
105     * @param n the number of elements to copy. This will be the new size of
106     * the list.
107     **/
108     private synchronized void copyIn(E[] toCopyIn, int first, int n) {
109 dl 1.12 array = (E[]) new Object[n];
110     System.arraycopy(toCopyIn, first, array, 0, n);
111 tim 1.1 }
112    
113     /**
114 dl 1.15 * Returns the number of elements in this list.
115 tim 1.1 *
116 dl 1.15 * @return the number of elements in this list.
117 tim 1.1 */
118     public int size() {
119     return array().length;
120     }
121    
122     /**
123 dl 1.15 * Tests if this list has no elements.
124 tim 1.1 *
125 dl 1.15 * @return <tt>true</tt> if this list has no elements;
126 dl 1.14 * <tt>false</tt> otherwise.
127 tim 1.1 */
128     public boolean isEmpty() {
129     return size() == 0;
130     }
131    
132     /**
133 dl 1.15 * Returns <tt>true</tt> if this list contains the specified element.
134 tim 1.1 *
135 dl 1.6 * @param elem element whose presence in this List is to be tested.
136 dl 1.15 * @return <code>true</code> if the specified element is present;
137 tim 1.22 * <code>false</code> otherwise.
138 tim 1.1 */
139     public boolean contains(Object elem) {
140     E[] elementData = array();
141     int len = elementData.length;
142     return indexOf(elem, elementData, len) >= 0;
143     }
144    
145     /**
146 dl 1.16 * Searches for the first occurrence of the given argument, testing
147 dl 1.15 * for equality using the <tt>equals</tt> method.
148 tim 1.1 *
149     * @param elem an object.
150     * @return the index of the first occurrence of the argument in this
151 dl 1.14 * list; returns <tt>-1</tt> if the object is not found.
152 tim 1.1 * @see Object#equals(Object)
153     */
154     public int indexOf(Object elem) {
155     E[] elementData = array();
156     int len = elementData.length;
157     return indexOf(elem, elementData, len);
158     }
159    
160     /**
161     * static version allows repeated call without needed
162     * to grab lock for array each time
163     **/
164     private static int indexOf(Object elem, Object[] elementData, int len) {
165     if (elem == null) {
166     for (int i = 0; i < len; i++)
167     if (elementData[i]==null)
168     return i;
169     } else {
170     for (int i = 0; i < len; i++)
171     if (elem.equals(elementData[i]))
172     return i;
173     }
174     return -1;
175     }
176    
177     /**
178 dl 1.16 * Searches for the first occurrence of the given argument, beginning
179 dl 1.14 * the search at <tt>index</tt>, and testing for equality using
180     * the <tt>equals</tt> method.
181 tim 1.1 *
182     * @param elem an object.
183     * @param index the index to start searching from.
184     * @return the index of the first occurrence of the object argument in
185 dl 1.14 * this List at position <tt>index</tt> or later in the
186     * List; returns <tt>-1</tt> if the object is not found.
187 tim 1.1 * @see Object#equals(Object)
188     */
189     public int indexOf(E elem, int index) {
190     E[] elementData = array();
191     int elementCount = elementData.length;
192    
193     if (elem == null) {
194     for (int i = index ; i < elementCount ; i++)
195     if (elementData[i]==null)
196     return i;
197     } else {
198     for (int i = index ; i < elementCount ; i++)
199     if (elem.equals(elementData[i]))
200     return i;
201     }
202     return -1;
203     }
204    
205     /**
206     * Returns the index of the last occurrence of the specified object in
207     * this list.
208     *
209 dl 1.15 * @param elem the desired element.
210 tim 1.1 * @return the index of the last occurrence of the specified object in
211     * this list; returns -1 if the object is not found.
212     */
213     public int lastIndexOf(Object elem) {
214     E[] elementData = array();
215     int len = elementData.length;
216     return lastIndexOf(elem, elementData, len);
217     }
218    
219     private static int lastIndexOf(Object elem, Object[] elementData, int len) {
220     if (elem == null) {
221     for (int i = len-1; i >= 0; i--)
222     if (elementData[i]==null)
223     return i;
224     } else {
225     for (int i = len-1; i >= 0; i--)
226     if (elem.equals(elementData[i]))
227     return i;
228     }
229     return -1;
230     }
231    
232     /**
233     * Searches backwards for the specified object, starting from the
234     * specified index, and returns an index to it.
235     *
236 dl 1.15 * @param elem the desired element.
237 tim 1.1 * @param index the index to start searching from.
238     * @return the index of the last occurrence of the specified object in this
239     * List at position less than index in the List;
240     * -1 if the object is not found.
241     */
242     public int lastIndexOf(E elem, int index) {
243     // needed in order to compile on 1.2b3
244     E[] elementData = array();
245     if (elem == null) {
246     for (int i = index; i >= 0; i--)
247     if (elementData[i]==null)
248     return i;
249     } else {
250     for (int i = index; i >= 0; i--)
251     if (elem.equals(elementData[i]))
252     return i;
253     }
254     return -1;
255     }
256    
257     /**
258     * Returns a shallow copy of this list. (The elements themselves
259     * are not copied.)
260     *
261     * @return a clone of this list.
262     */
263     public Object clone() {
264     try {
265     E[] elementData = array();
266 tim 1.8 CopyOnWriteArrayList<E> v = (CopyOnWriteArrayList<E>)super.clone();
267 dl 1.12 v.array = (E[]) new Object[elementData.length];
268     System.arraycopy(elementData, 0, v.array, 0, elementData.length);
269 tim 1.1 return v;
270     } catch (CloneNotSupportedException e) {
271     // this shouldn't happen, since we are Cloneable
272     throw new InternalError();
273     }
274     }
275    
276     /**
277     * Returns an array containing all of the elements in this list
278     * in the correct order.
279 dl 1.15 * @return an array containing all of the elements in this list
280 tim 1.22 * in the correct order.
281 tim 1.1 */
282     public Object[] toArray() {
283     Object[] elementData = array();
284     Object[] result = new Object[elementData.length];
285     System.arraycopy(elementData, 0, result, 0, elementData.length);
286     return result;
287     }
288    
289     /**
290     * Returns an array containing all of the elements in this list in the
291     * correct order. The runtime type of the returned array is that of the
292     * specified array. If the list fits in the specified array, it is
293     * returned therein. Otherwise, a new array is allocated with the runtime
294     * type of the specified array and the size of this list.
295     * <p>
296     * If the list fits in the specified array with room to spare
297     * (i.e., the array has more elements than the list),
298     * the element in the array immediately following the end of the
299     * collection is set to null. This is useful in determining the length
300     * of the list <em>only</em> if the caller knows that the list
301     * does not contain any null elements.
302     *
303     * @param a the array into which the elements of the list are to
304     * be stored, if it is big enough; otherwise, a new array of the
305     * same runtime type is allocated for this purpose.
306     * @return an array containing the elements of the list.
307 dl 1.6 * @throws ArrayStoreException the runtime type of a is not a supertype
308 tim 1.1 * of the runtime type of every element in this list.
309     */
310     public <T> T[] toArray(T a[]) {
311     E[] elementData = array();
312    
313     if (a.length < elementData.length)
314     a = (T[])
315     java.lang.reflect.Array.newInstance(a.getClass().getComponentType(),
316     elementData.length);
317    
318     System.arraycopy(elementData, 0, a, 0, elementData.length);
319    
320     if (a.length > elementData.length)
321     a[elementData.length] = null;
322    
323     return a;
324     }
325    
326     // Positional Access Operations
327    
328     /**
329     * Returns the element at the specified position in this list.
330     *
331 dl 1.15 * @param index index of element to return.
332     * @return the element at the specified position in this list.
333     * @throws IndexOutOfBoundsException if index is out of range <tt>(index
334 tim 1.22 * &lt; 0 || index &gt;= size())</tt>.
335 tim 1.1 */
336     public E get(int index) {
337     E[] elementData = array();
338     rangeCheck(index, elementData.length);
339     return elementData[index];
340     }
341    
342     /**
343     * Replaces the element at the specified position in this list with
344     * the specified element.
345     *
346     * @param index index of element to replace.
347     * @param element element to be stored at the specified position.
348     * @return the element previously at the specified position.
349 dl 1.15 * @throws IndexOutOfBoundsException if index out of range
350 tim 1.22 * <tt>(index &lt; 0 || index &gt;= size())</tt>.
351 tim 1.1 */
352     public synchronized E set(int index, E element) {
353 dl 1.12 int len = array.length;
354 tim 1.1 rangeCheck(index, len);
355 dl 1.12 E oldValue = array[index];
356 tim 1.1
357     boolean same = (oldValue == element ||
358     (element != null && element.equals(oldValue)));
359     if (!same) {
360 tim 1.7 E[] newArray = (E[]) new Object[len];
361 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
362 tim 1.1 newArray[index] = element;
363 dl 1.12 array = newArray;
364 tim 1.1 }
365     return oldValue;
366     }
367    
368     /**
369     * Appends the specified element to the end of this list.
370     *
371     * @param element element to be appended to this list.
372     * @return true (as per the general contract of Collection.add).
373     */
374     public synchronized boolean add(E element) {
375 dl 1.12 int len = array.length;
376 tim 1.7 E[] newArray = (E[]) new Object[len+1];
377 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
378 tim 1.1 newArray[len] = element;
379 dl 1.12 array = newArray;
380 tim 1.1 return true;
381     }
382    
383     /**
384     * Inserts the specified element at the specified position in this
385     * list. Shifts the element currently at that position (if any) and
386     * any subsequent elements to the right (adds one to their indices).
387     *
388     * @param index index at which the specified element is to be inserted.
389     * @param element element to be inserted.
390 dl 1.15 * @throws IndexOutOfBoundsException if index is out of range
391 tim 1.22 * <tt>(index &lt; 0 || index &gt; size())</tt>.
392 tim 1.1 */
393     public synchronized void add(int index, E element) {
394 dl 1.12 int len = array.length;
395 tim 1.1 if (index > len || index < 0)
396     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+len);
397    
398 tim 1.7 E[] newArray = (E[]) new Object[len+1];
399 dl 1.12 System.arraycopy(array, 0, newArray, 0, index);
400 tim 1.1 newArray[index] = element;
401 dl 1.12 System.arraycopy(array, index, newArray, index+1, len - index);
402     array = newArray;
403 tim 1.1 }
404    
405     /**
406     * Removes the element at the specified position in this list.
407     * Shifts any subsequent elements to the left (subtracts one from their
408 dl 1.15 * indices).
409 tim 1.1 *
410     * @param index the index of the element to removed.
411 dl 1.15 * @return the element that was removed from the list.
412     * @throws IndexOutOfBoundsException if index out of range <tt>(index
413 tim 1.22 * &lt; 0 || index &gt;= size())</tt>.
414 tim 1.1 */
415     public synchronized E remove(int index) {
416 dl 1.12 int len = array.length;
417 tim 1.1 rangeCheck(index, len);
418 dl 1.12 E oldValue = array[index];
419 tim 1.7 E[] newArray = (E[]) new Object[len-1];
420 dl 1.12 System.arraycopy(array, 0, newArray, 0, index);
421 tim 1.1 int numMoved = len - index - 1;
422     if (numMoved > 0)
423 dl 1.12 System.arraycopy(array, index+1, newArray, index, numMoved);
424     array = newArray;
425 tim 1.1 return oldValue;
426     }
427    
428     /**
429 dl 1.15 * Removes a single instance of the specified element from this
430     * list, if it is present (optional operation). More formally,
431     * removes an element <tt>e</tt> such that <tt>(o==null ? e==null :
432     * o.equals(e))</tt>, if the list contains one or more such
433     * elements. Returns <tt>true</tt> if the list contained the
434     * specified element (or equivalently, if the list changed as a
435     * result of the call).<p>
436 tim 1.1 *
437 dl 1.15 * @param o element to be removed from this list, if present.
438     * @return <tt>true</tt> if the list contained the specified element.
439 tim 1.1 */
440 dl 1.15 public synchronized boolean remove(Object o) {
441 dl 1.12 int len = array.length;
442 tim 1.1 if (len == 0) return false;
443    
444     // Copy while searching for element to remove
445     // This wins in the normal case of element being present
446    
447     int newlen = len-1;
448 tim 1.7 E[] newArray = (E[]) new Object[newlen];
449 tim 1.1
450     for (int i = 0; i < newlen; ++i) {
451 dl 1.15 if (o == array[i] ||
452     (o != null && o.equals(array[i]))) {
453 tim 1.1 // found one; copy remaining and exit
454 dl 1.12 for (int k = i + 1; k < len; ++k) newArray[k-1] = array[k];
455     array = newArray;
456 tim 1.1 return true;
457 tim 1.10 } else
458 dl 1.12 newArray[i] = array[i];
459 tim 1.1 }
460     // special handling for last cell
461    
462 dl 1.15 if (o == array[newlen] ||
463     (o != null && o.equals(array[newlen]))) {
464 dl 1.12 array = newArray;
465 tim 1.1 return true;
466 tim 1.10 } else
467 tim 1.1 return false; // throw away copy
468     }
469    
470    
471     /**
472     * Removes from this List all of the elements whose index is between
473     * fromIndex, inclusive and toIndex, exclusive. Shifts any succeeding
474     * elements to the left (reduces their index).
475 dl 1.15 * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
476     * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
477 tim 1.1 *
478     * @param fromIndex index of first element to be removed.
479 dl 1.6 * @param toIndex index after last element to be removed.
480     * @throws IndexOutOfBoundsException fromIndex or toIndex out of
481 tim 1.1 * range (fromIndex &lt; 0 || fromIndex &gt;= size() || toIndex
482     * &gt; size() || toIndex &lt; fromIndex).
483     */
484     private synchronized void removeRange(int fromIndex, int toIndex) {
485 dl 1.12 int len = array.length;
486 tim 1.1
487     if (fromIndex < 0 || fromIndex >= len ||
488     toIndex > len || toIndex < fromIndex)
489     throw new IndexOutOfBoundsException();
490    
491     int numMoved = len - toIndex;
492     int newlen = len - (toIndex-fromIndex);
493 tim 1.7 E[] newArray = (E[]) new Object[newlen];
494 dl 1.12 System.arraycopy(array, 0, newArray, 0, fromIndex);
495     System.arraycopy(array, toIndex, newArray, fromIndex, numMoved);
496     array = newArray;
497 tim 1.1 }
498    
499    
500     /**
501     * Append the element if not present.
502     * @param element element to be added to this Collection, if absent.
503     * @return true if added
504     **/
505     public synchronized boolean addIfAbsent(E element) {
506     // Copy while checking if already present.
507     // This wins in the most common case where it is not present
508 dl 1.12 int len = array.length;
509 tim 1.7 E[] newArray = (E[]) new Object[len + 1];
510 tim 1.1 for (int i = 0; i < len; ++i) {
511 dl 1.12 if (element == array[i] ||
512     (element != null && element.equals(array[i])))
513 tim 1.1 return false; // exit, throwing away copy
514     else
515 dl 1.12 newArray[i] = array[i];
516 tim 1.1 }
517     newArray[len] = element;
518 dl 1.12 array = newArray;
519 tim 1.1 return true;
520     }
521    
522     /**
523     * Returns true if this Collection contains all of the elements in the
524     * specified Collection.
525     * <p>
526     * This implementation iterates over the specified Collection, checking
527     * each element returned by the Iterator in turn to see if it's
528     * contained in this Collection. If all elements are so contained
529     * true is returned, otherwise false.
530 dl 1.6 * @param c the collection
531     * @return true if all elements are contained
532 tim 1.1 */
533 tim 1.7 public boolean containsAll(Collection<?> c) {
534 tim 1.1 E[] elementData = array();
535     int len = elementData.length;
536 tim 1.7 Iterator e = c.iterator();
537 tim 1.1 while (e.hasNext())
538 dl 1.20 if (indexOf(e.next(), elementData, len) < 0)
539 tim 1.1 return false;
540    
541     return true;
542     }
543    
544    
545     /**
546     * Removes from this Collection all of its elements that are contained in
547     * the specified Collection. This is a particularly expensive operation
548     * in this class because of the need for an internal temporary array.
549     * <p>
550     *
551 dl 1.6 * @param c the collection
552 tim 1.1 * @return true if this Collection changed as a result of the call.
553     */
554 tim 1.7 public synchronized boolean removeAll(Collection<?> c) {
555 dl 1.12 E[] elementData = array;
556 tim 1.1 int len = elementData.length;
557     if (len == 0) return false;
558    
559     // temp array holds those elements we know we want to keep
560 tim 1.7 E[] temp = (E[]) new Object[len];
561 tim 1.1 int newlen = 0;
562     for (int i = 0; i < len; ++i) {
563     E element = elementData[i];
564     if (!c.contains(element)) {
565     temp[newlen++] = element;
566     }
567     }
568    
569     if (newlen == len) return false;
570    
571     // copy temp as new array
572 tim 1.7 E[] newArray = (E[]) new Object[newlen];
573 tim 1.1 System.arraycopy(temp, 0, newArray, 0, newlen);
574 dl 1.12 array = newArray;
575 tim 1.1 return true;
576     }
577    
578     /**
579     * Retains only the elements in this Collection that are contained in the
580     * specified Collection (optional operation). In other words, removes from
581     * this Collection all of its elements that are not contained in the
582     * specified Collection.
583 dl 1.6 * @param c the collection
584 tim 1.1 * @return true if this Collection changed as a result of the call.
585     */
586 tim 1.7 public synchronized boolean retainAll(Collection<?> c) {
587 dl 1.12 E[] elementData = array;
588 tim 1.1 int len = elementData.length;
589     if (len == 0) return false;
590    
591 tim 1.7 E[] temp = (E[]) new Object[len];
592 tim 1.1 int newlen = 0;
593     for (int i = 0; i < len; ++i) {
594     E element = elementData[i];
595     if (c.contains(element)) {
596     temp[newlen++] = element;
597     }
598     }
599    
600     if (newlen == len) return false;
601    
602 tim 1.7 E[] newArray = (E[]) new Object[newlen];
603 tim 1.1 System.arraycopy(temp, 0, newArray, 0, newlen);
604 dl 1.12 array = newArray;
605 tim 1.1 return true;
606     }
607    
608     /**
609     * Appends all of the elements in the specified Collection that
610     * are not already contained in this list, to the end of
611     * this list, in the order that they are returned by the
612     * specified Collection's Iterator.
613     *
614     * @param c elements to be added into this list.
615     * @return the number of elements added
616     */
617 tim 1.7 public synchronized int addAllAbsent(Collection<? extends E> c) {
618 tim 1.1 int numNew = c.size();
619     if (numNew == 0) return 0;
620    
621 dl 1.12 E[] elementData = array;
622 tim 1.1 int len = elementData.length;
623    
624 tim 1.7 E[] temp = (E[]) new Object[numNew];
625 tim 1.1 int added = 0;
626 dl 1.20 Iterator<? extends E> e = c.iterator();
627 tim 1.1 while (e.hasNext()) {
628 dl 1.20 E element = e.next();
629 tim 1.1 if (indexOf(element, elementData, len) < 0) {
630     if (indexOf(element, temp, added) < 0) {
631     temp[added++] = element;
632     }
633     }
634     }
635    
636     if (added == 0) return 0;
637    
638 tim 1.7 E[] newArray = (E[]) new Object[len+added];
639 tim 1.1 System.arraycopy(elementData, 0, newArray, 0, len);
640     System.arraycopy(temp, 0, newArray, len, added);
641 dl 1.12 array = newArray;
642 tim 1.1 return added;
643     }
644    
645     /**
646     * Removes all of the elements from this list.
647     *
648     */
649     public synchronized void clear() {
650 dl 1.12 array = (E[]) new Object[0];
651 tim 1.1 }
652    
653     /**
654     * Appends all of the elements in the specified Collection to the end of
655     * this list, in the order that they are returned by the
656     * specified Collection's Iterator.
657     *
658     * @param c elements to be inserted into this list.
659 dl 1.6 * @return true if any elements are added
660 tim 1.1 */
661 tim 1.7 public synchronized boolean addAll(Collection<? extends E> c) {
662 tim 1.1 int numNew = c.size();
663     if (numNew == 0) return false;
664    
665 dl 1.12 int len = array.length;
666 tim 1.7 E[] newArray = (E[]) new Object[len+numNew];
667 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
668 dl 1.20 Iterator<? extends E> e = c.iterator();
669 tim 1.1 for (int i=0; i<numNew; i++)
670 dl 1.20 newArray[len++] = e.next();
671 dl 1.12 array = newArray;
672 tim 1.1
673     return true;
674     }
675    
676     /**
677     * Inserts all of the elements in the specified Collection into this
678     * list, starting at the specified position. Shifts the element
679     * currently at that position (if any) and any subsequent elements to
680     * the right (increases their indices). The new elements will appear
681     * in the list in the order that they are returned by the
682     * specified Collection's iterator.
683     *
684     * @param index index at which to insert first element
685     * from the specified collection.
686     * @param c elements to be inserted into this list.
687 dl 1.6 * @throws IndexOutOfBoundsException index out of range (index
688 tim 1.1 * &lt; 0 || index &gt; size()).
689 dl 1.6 * @return true if any elements are added
690 tim 1.1 */
691 tim 1.7 public synchronized boolean addAll(int index, Collection<? extends E> c) {
692 dl 1.12 int len = array.length;
693 tim 1.1 if (index > len || index < 0)
694     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+len);
695    
696     int numNew = c.size();
697     if (numNew == 0) return false;
698    
699 tim 1.7 E[] newArray = (E[]) new Object[len+numNew];
700 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
701 tim 1.1 int numMoved = len - index;
702     if (numMoved > 0)
703 dl 1.12 System.arraycopy(array, index, newArray, index + numNew, numMoved);
704 dl 1.20 Iterator<? extends E> e = c.iterator();
705 tim 1.1 for (int i=0; i<numNew; i++)
706 dl 1.20 newArray[index++] = e.next();
707 dl 1.12 array = newArray;
708 tim 1.1
709     return true;
710     }
711    
712     /**
713     * Check if the given index is in range. If not, throw an appropriate
714     * runtime exception.
715     */
716     private void rangeCheck(int index, int length) {
717     if (index >= length || index < 0)
718     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+ length);
719     }
720    
721     /**
722     * Save the state of the list to a stream (i.e., serialize it).
723     *
724     * @serialData The length of the array backing the list is emitted
725     * (int), followed by all of its elements (each an Object)
726     * in the proper order.
727 dl 1.6 * @param s the stream
728 tim 1.1 */
729     private void writeObject(java.io.ObjectOutputStream s)
730     throws java.io.IOException{
731    
732     // Write out element count, and any hidden stuff
733     s.defaultWriteObject();
734    
735     E[] elementData = array();
736     // Write out array length
737     s.writeInt(elementData.length);
738    
739     // Write out all elements in the proper order.
740     for (int i=0; i<elementData.length; i++)
741     s.writeObject(elementData[i]);
742     }
743    
744     /**
745     * Reconstitute the list from a stream (i.e., deserialize it).
746 dl 1.6 * @param s the stream
747 tim 1.1 */
748 dl 1.12 private void readObject(java.io.ObjectInputStream s)
749 tim 1.1 throws java.io.IOException, ClassNotFoundException {
750    
751     // Read in size, and any hidden stuff
752     s.defaultReadObject();
753    
754     // Read in array length and allocate array
755     int arrayLength = s.readInt();
756 tim 1.7 E[] elementData = (E[]) new Object[arrayLength];
757 tim 1.1
758     // Read in all elements in the proper order.
759     for (int i=0; i<elementData.length; i++)
760     elementData[i] = (E) s.readObject();
761 dl 1.12 array = elementData;
762 tim 1.1 }
763    
764     /**
765     * Returns a string representation of this Collection, containing
766     * the String representation of each element.
767     */
768     public String toString() {
769     StringBuffer buf = new StringBuffer();
770     Iterator e = iterator();
771     buf.append("[");
772     int maxIndex = size() - 1;
773     for (int i = 0; i <= maxIndex; i++) {
774     buf.append(String.valueOf(e.next()));
775     if (i < maxIndex)
776     buf.append(", ");
777     }
778     buf.append("]");
779     return buf.toString();
780     }
781    
782    
783     /**
784     * Compares the specified Object with this List for equality. Returns true
785     * if and only if the specified Object is also a List, both Lists have the
786     * same size, and all corresponding pairs of elements in the two Lists are
787 dl 1.14 * <em>equal</em>. (Two elements <tt>e1</tt> and <tt>e2</tt> are
788     * <em>equal</em> if <tt>(e1==null ? e2==null : e1.equals(e2))</tt>.)
789 tim 1.1 * In other words, two Lists are defined to be equal if they contain the
790     * same elements in the same order.
791     * <p>
792     * This implementation first checks if the specified object is this
793     * List. If so, it returns true; if not, it checks if the specified
794     * object is a List. If not, it returns false; if so, it iterates over
795     * both lists, comparing corresponding pairs of elements. If any
796     * comparison returns false, this method returns false. If either
797     * Iterator runs out of elements before before the other it returns false
798     * (as the Lists are of unequal length); otherwise it returns true when
799     * the iterations complete.
800     *
801     * @param o the Object to be compared for equality with this List.
802     * @return true if the specified Object is equal to this List.
803     */
804     public boolean equals(Object o) {
805     if (o == this)
806     return true;
807     if (!(o instanceof List))
808     return false;
809    
810 tim 1.8 List<E> l2 = (List<E>)(o);
811 tim 1.1 if (size() != l2.size())
812     return false;
813    
814     ListIterator<E> e1 = listIterator();
815     ListIterator<E> e2 = l2.listIterator();
816     while(e1.hasNext()) {
817     E o1 = e1.next();
818     E o2 = e2.next();
819     if (!(o1==null ? o2==null : o1.equals(o2)))
820     return false;
821     }
822     return true;
823     }
824    
825     /**
826 dl 1.15 * Returns the hash code value for this List. <p> This
827     * implementation uses the definition in {@link List#hashCode}.
828     * @return the hash code
829 tim 1.1 */
830     public int hashCode() {
831     int hashCode = 1;
832     Iterator<E> i = iterator();
833     while (i.hasNext()) {
834     E obj = i.next();
835     hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
836     }
837     return hashCode;
838     }
839    
840     /**
841     * Returns an Iterator over the elements contained in this collection.
842     * The iterator provides a snapshot of the state of the list
843     * when the iterator was constructed. No synchronization is
844     * needed while traversing the iterator. The iterator does
845 dl 1.14 * <em>NOT</em> support the <tt>remove</tt> method.
846 dl 1.23 * @return the iterator
847 tim 1.1 */
848     public Iterator<E> iterator() {
849     return new COWIterator<E>(array(), 0);
850     }
851    
852     /**
853     * Returns an Iterator of the elements in this List (in proper sequence).
854     * The iterator provides a snapshot of the state of the list
855     * when the iterator was constructed. No synchronization is
856     * needed while traversing the iterator. The iterator does
857 dl 1.14 * <em>NOT</em> support the <tt>remove</tt>, <tt>set</tt>,
858     * or <tt>add</tt> methods.
859 dl 1.23 * @return the iterator
860 tim 1.1 *
861     */
862     public ListIterator<E> listIterator() {
863     return new COWIterator<E>(array(), 0);
864     }
865    
866     /**
867     * Returns a ListIterator of the elements in this List (in proper
868     * sequence), starting at the specified position in the List. The
869     * specified index indicates the first element that would be returned by
870     * an initial call to nextElement. An initial call to previousElement
871     * would return the element with the specified index minus one.
872     * The ListIterator returned by this implementation will throw
873     * an UnsupportedOperationException in its remove, set and
874     * add methods.
875     *
876     * @param index index of first element to be returned from the
877     * ListIterator (by a call to getNext).
878 dl 1.23 * @return the iterator
879 dl 1.6 * @throws IndexOutOfBoundsException index is out of range
880 tim 1.1 * (index &lt; 0 || index &gt; size()).
881     */
882     public ListIterator<E> listIterator(final int index) {
883     E[] elementData = array();
884     int len = elementData.length;
885     if (index<0 || index>len)
886     throw new IndexOutOfBoundsException("Index: "+index);
887    
888     return new COWIterator<E>(array(), index);
889     }
890    
891     private static class COWIterator<E> implements ListIterator<E> {
892    
893     /** Snapshot of the array **/
894     private final E[] array;
895    
896     /**
897     * Index of element to be returned by subsequent call to next.
898     */
899     private int cursor;
900    
901     private COWIterator(E[] elementArray, int initialCursor) {
902     array = elementArray;
903     cursor = initialCursor;
904     }
905    
906     public boolean hasNext() {
907     return cursor < array.length;
908     }
909    
910     public boolean hasPrevious() {
911     return cursor > 0;
912     }
913    
914     public E next() {
915     try {
916     return array[cursor++];
917 tim 1.10 } catch (IndexOutOfBoundsException ex) {
918 tim 1.1 throw new NoSuchElementException();
919     }
920     }
921    
922     public E previous() {
923     try {
924     return array[--cursor];
925     } catch(IndexOutOfBoundsException e) {
926     throw new NoSuchElementException();
927     }
928     }
929    
930     public int nextIndex() {
931     return cursor;
932     }
933    
934     public int previousIndex() {
935     return cursor-1;
936     }
937    
938     /**
939     * Not supported. Always throws UnsupportedOperationException.
940 dl 1.6 * @throws UnsupportedOperationException remove is not supported
941 tim 1.1 * by this Iterator.
942     */
943    
944     public void remove() {
945     throw new UnsupportedOperationException();
946     }
947    
948     /**
949     * Not supported. Always throws UnsupportedOperationException.
950 dl 1.6 * @throws UnsupportedOperationException set is not supported
951 tim 1.1 * by this Iterator.
952     */
953     public void set(E o) {
954     throw new UnsupportedOperationException();
955     }
956    
957     /**
958     * Not supported. Always throws UnsupportedOperationException.
959 dl 1.6 * @throws UnsupportedOperationException add is not supported
960 tim 1.1 * by this Iterator.
961     */
962     public void add(E o) {
963     throw new UnsupportedOperationException();
964     }
965     }
966    
967    
968     /**
969     * Returns a view of the portion of this List between fromIndex,
970     * inclusive, and toIndex, exclusive. The returned List is backed by this
971     * List, so changes in the returned List are reflected in this List, and
972     * vice-versa. While mutative operations are supported, they are
973 dl 1.16 * probably not very useful for CopyOnWriteArrayLists.
974 tim 1.9 * <p>
975 tim 1.1 * The semantics of the List returned by this method become undefined if
976     * the backing list (i.e., this List) is <i>structurally modified</i> in
977     * any way other than via the returned List. (Structural modifications are
978     * those that change the size of the List, or otherwise perturb it in such
979     * a fashion that iterations in progress may yield incorrect results.)
980     *
981     * @param fromIndex low endpoint (inclusive) of the subList.
982 dl 1.6 * @param toIndex high endpoint (exclusive) of the subList.
983 tim 1.1 * @return a view of the specified range within this List.
984 dl 1.6 * @throws IndexOutOfBoundsException Illegal endpoint index value
985 tim 1.1 * (fromIndex &lt; 0 || toIndex &gt; size || fromIndex &gt; toIndex).
986     */
987     public synchronized List<E> subList(int fromIndex, int toIndex) {
988 dl 1.21 // synchronized since sublist constructor depends on it.
989 dl 1.12 int len = array.length;
990 tim 1.1 if (fromIndex<0 || toIndex>len || fromIndex>toIndex)
991     throw new IndexOutOfBoundsException();
992     return new COWSubList<E>(this, fromIndex, toIndex);
993     }
994    
995     private static class COWSubList<E> extends AbstractList<E> {
996    
997     /*
998 dl 1.2 This class extends AbstractList merely for convenience, to
999     avoid having to define addAll, etc. This doesn't hurt, but
1000     is wasteful. This class does not need or use modCount
1001     mechanics in AbstractList, but does need to check for
1002     concurrent modification using similar mechanics. On each
1003     operation, the array that we expect the backing list to use
1004     is checked and updated. Since we do this for all of the
1005     base operations invoked by those defined in AbstractList,
1006     all is well. While inefficient, this is not worth
1007     improving. The kinds of list operations inherited from
1008 dl 1.20 AbstractList are already so slow on COW sublists that
1009 dl 1.2 adding a bit more space/time doesn't seem even noticeable.
1010 tim 1.1 */
1011    
1012     private final CopyOnWriteArrayList<E> l;
1013     private final int offset;
1014     private int size;
1015     private E[] expectedArray;
1016    
1017     private COWSubList(CopyOnWriteArrayList<E> list,
1018     int fromIndex, int toIndex) {
1019     l = list;
1020     expectedArray = l.array();
1021     offset = fromIndex;
1022     size = toIndex - fromIndex;
1023     }
1024    
1025     // only call this holding l's lock
1026     private void checkForComodification() {
1027 dl 1.12 if (l.array != expectedArray)
1028 tim 1.1 throw new ConcurrentModificationException();
1029     }
1030    
1031     // only call this holding l's lock
1032     private void rangeCheck(int index) {
1033     if (index<0 || index>=size)
1034     throw new IndexOutOfBoundsException("Index: "+index+ ",Size: "+size);
1035     }
1036    
1037    
1038     public E set(int index, E element) {
1039     synchronized(l) {
1040     rangeCheck(index);
1041     checkForComodification();
1042     E x = l.set(index+offset, element);
1043 dl 1.12 expectedArray = l.array;
1044 tim 1.1 return x;
1045     }
1046     }
1047    
1048     public E get(int index) {
1049     synchronized(l) {
1050     rangeCheck(index);
1051     checkForComodification();
1052     return l.get(index+offset);
1053     }
1054     }
1055    
1056     public int size() {
1057     synchronized(l) {
1058     checkForComodification();
1059     return size;
1060     }
1061     }
1062    
1063     public void add(int index, E element) {
1064     synchronized(l) {
1065     checkForComodification();
1066     if (index<0 || index>size)
1067     throw new IndexOutOfBoundsException();
1068     l.add(index+offset, element);
1069 dl 1.12 expectedArray = l.array;
1070 tim 1.1 size++;
1071     }
1072     }
1073    
1074 dl 1.13 public void clear() {
1075     synchronized(l) {
1076     checkForComodification();
1077     l.removeRange(offset, offset+size);
1078     expectedArray = l.array;
1079     size = 0;
1080     }
1081     }
1082    
1083 tim 1.1 public E remove(int index) {
1084     synchronized(l) {
1085     rangeCheck(index);
1086     checkForComodification();
1087     E result = l.remove(index+offset);
1088 dl 1.12 expectedArray = l.array;
1089 tim 1.1 size--;
1090     return result;
1091     }
1092     }
1093    
1094     public Iterator<E> iterator() {
1095     synchronized(l) {
1096     checkForComodification();
1097 tim 1.8 return new COWSubListIterator<E>(l, 0, offset, size);
1098 tim 1.1 }
1099     }
1100    
1101     public ListIterator<E> listIterator(final int index) {
1102     synchronized(l) {
1103     checkForComodification();
1104     if (index<0 || index>size)
1105     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
1106 tim 1.8 return new COWSubListIterator<E>(l, index, offset, size);
1107 tim 1.1 }
1108     }
1109    
1110 tim 1.7 public List<E> subList(int fromIndex, int toIndex) {
1111     synchronized(l) {
1112     checkForComodification();
1113     if (fromIndex<0 || toIndex>size)
1114     throw new IndexOutOfBoundsException();
1115     return new COWSubList<E>(l, fromIndex+offset, toIndex+offset);
1116 tim 1.1 }
1117 tim 1.7 }
1118 tim 1.1
1119 tim 1.7 }
1120 tim 1.1
1121    
1122 tim 1.7 private static class COWSubListIterator<E> implements ListIterator<E> {
1123     private final ListIterator<E> i;
1124     private final int index;
1125     private final int offset;
1126     private final int size;
1127     private COWSubListIterator(List<E> l, int index, int offset, int size) {
1128     this.index = index;
1129     this.offset = offset;
1130     this.size = size;
1131     i = l.listIterator(index+offset);
1132     }
1133 tim 1.1
1134 tim 1.7 public boolean hasNext() {
1135     return nextIndex() < size;
1136     }
1137 tim 1.1
1138 tim 1.7 public E next() {
1139     if (hasNext())
1140     return i.next();
1141     else
1142     throw new NoSuchElementException();
1143     }
1144 tim 1.1
1145 tim 1.7 public boolean hasPrevious() {
1146     return previousIndex() >= 0;
1147     }
1148 tim 1.1
1149 tim 1.7 public E previous() {
1150     if (hasPrevious())
1151     return i.previous();
1152     else
1153     throw new NoSuchElementException();
1154     }
1155 tim 1.1
1156 tim 1.7 public int nextIndex() {
1157     return i.nextIndex() - offset;
1158     }
1159 tim 1.1
1160 tim 1.7 public int previousIndex() {
1161     return i.previousIndex() - offset;
1162 tim 1.1 }
1163    
1164 tim 1.7 public void remove() {
1165     throw new UnsupportedOperationException();
1166     }
1167 tim 1.1
1168 tim 1.7 public void set(E o) {
1169     throw new UnsupportedOperationException();
1170 tim 1.1 }
1171    
1172 tim 1.7 public void add(E o) {
1173     throw new UnsupportedOperationException();
1174     }
1175 tim 1.1 }
1176    
1177     }