ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.10
Committed: Fri Aug 8 20:05:07 2003 UTC (20 years, 9 months ago) by tim
Branch: MAIN
Changes since 1.9: +3 -6 lines
Log Message:
Scrunched catch, finally, else clauses.

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