ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.15
Committed: Sat Sep 13 18:51:11 2003 UTC (20 years, 8 months ago) by dl
Branch: MAIN
Changes since 1.14: +57 -54 lines
Log Message:
Proofreading pass -- many minor adjustments

File Contents

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