ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.30
Committed: Tue Apr 26 01:43:01 2005 UTC (19 years, 1 month ago) by jsr166
Branch: MAIN
Changes since 1.29: +14 -14 lines
Log Message:
doc fixes

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