ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.9
Committed: Wed Aug 6 18:22:09 2003 UTC (20 years, 10 months ago) by tim
Branch: MAIN
CVS Tags: JSR166_CR1
Changes since 1.8: +6 -6 lines
Log Message:
Fixes to minor errors found by DocCheck

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     }
451     else
452     newArray[i] = array_[i];
453     }
454     // special handling for last cell
455    
456     if (element == array_[newlen] ||
457     (element != null && element.equals(array_[newlen]))) {
458     array_ = newArray;
459     return true;
460     }
461     else
462     return false; // throw away copy
463    
464     }
465    
466    
467     /**
468     * Removes from this List all of the elements whose index is between
469     * fromIndex, inclusive and toIndex, exclusive. Shifts any succeeding
470     * elements to the left (reduces their index).
471     * This call shortens the List by (toIndex - fromIndex) elements. (If
472     * toIndex==fromIndex, this operation has no effect.)
473     *
474     * @param fromIndex index of first element to be removed.
475 dl 1.6 * @param toIndex index after last element to be removed.
476     * @throws IndexOutOfBoundsException fromIndex or toIndex out of
477 tim 1.1 * range (fromIndex &lt; 0 || fromIndex &gt;= size() || toIndex
478     * &gt; size() || toIndex &lt; fromIndex).
479     */
480     private synchronized void removeRange(int fromIndex, int toIndex) {
481     int len = array_.length;
482    
483     if (fromIndex < 0 || fromIndex >= len ||
484     toIndex > len || toIndex < fromIndex)
485     throw new IndexOutOfBoundsException();
486    
487     int numMoved = len - toIndex;
488     int newlen = len - (toIndex-fromIndex);
489 tim 1.7 E[] newArray = (E[]) new Object[newlen];
490 tim 1.1 System.arraycopy(array_, 0, newArray, 0, fromIndex);
491     System.arraycopy(array_, toIndex, newArray, fromIndex, numMoved);
492     array_ = newArray;
493     }
494    
495    
496     /**
497     * Append the element if not present.
498     * This operation can be used to obtain Set semantics
499     * for lists.
500     * @param element element to be added to this Collection, if absent.
501     * @return true if added
502     **/
503     public synchronized boolean addIfAbsent(E element) {
504     // Copy while checking if already present.
505     // This wins in the most common case where it is not present
506     int len = array_.length;
507 tim 1.7 E[] newArray = (E[]) new Object[len + 1];
508 tim 1.1 for (int i = 0; i < len; ++i) {
509     if (element == array_[i] ||
510     (element != null && element.equals(array_[i])))
511     return false; // exit, throwing away copy
512     else
513     newArray[i] = array_[i];
514     }
515     newArray[len] = element;
516     array_ = newArray;
517     return true;
518     }
519    
520     /**
521     * Returns true if this Collection contains all of the elements in the
522     * specified Collection.
523     * <p>
524     * This implementation iterates over the specified Collection, checking
525     * each element returned by the Iterator in turn to see if it's
526     * contained in this Collection. If all elements are so contained
527     * true is returned, otherwise false.
528 dl 1.6 * @param c the collection
529     * @return true if all elements are contained
530 tim 1.1 */
531 tim 1.7 public boolean containsAll(Collection<?> c) {
532 tim 1.1 E[] elementData = array();
533     int len = elementData.length;
534 tim 1.7 Iterator e = c.iterator();
535 tim 1.1 while (e.hasNext())
536 tim 1.7 if (indexOf((E) e.next(), elementData, len) < 0)
537 tim 1.1 return false;
538    
539     return true;
540     }
541    
542    
543     /**
544     * Removes from this Collection all of its elements that are contained in
545     * the specified Collection. This is a particularly expensive operation
546     * in this class because of the need for an internal temporary array.
547     * <p>
548     *
549 dl 1.6 * @param c the collection
550 tim 1.1 * @return true if this Collection changed as a result of the call.
551     */
552 tim 1.7 public synchronized boolean removeAll(Collection<?> c) {
553 tim 1.1 E[] elementData = array_;
554     int len = elementData.length;
555     if (len == 0) return false;
556    
557     // temp array holds those elements we know we want to keep
558 tim 1.7 E[] temp = (E[]) new Object[len];
559 tim 1.1 int newlen = 0;
560     for (int i = 0; i < len; ++i) {
561     E element = elementData[i];
562     if (!c.contains(element)) {
563     temp[newlen++] = element;
564     }
565     }
566    
567     if (newlen == len) return false;
568    
569     // copy temp as new array
570 tim 1.7 E[] newArray = (E[]) new Object[newlen];
571 tim 1.1 System.arraycopy(temp, 0, newArray, 0, newlen);
572     array_ = newArray;
573     return true;
574     }
575    
576     /**
577     * Retains only the elements in this Collection that are contained in the
578     * specified Collection (optional operation). In other words, removes from
579     * this Collection all of its elements that are not contained in the
580     * specified Collection.
581 dl 1.6 * @param c the collection
582 tim 1.1 * @return true if this Collection changed as a result of the call.
583     */
584 tim 1.7 public synchronized boolean retainAll(Collection<?> c) {
585 tim 1.1 E[] elementData = array_;
586     int len = elementData.length;
587     if (len == 0) return false;
588    
589 tim 1.7 E[] temp = (E[]) new Object[len];
590 tim 1.1 int newlen = 0;
591     for (int i = 0; i < len; ++i) {
592     E element = elementData[i];
593     if (c.contains(element)) {
594     temp[newlen++] = element;
595     }
596     }
597    
598     if (newlen == len) return false;
599    
600 tim 1.7 E[] newArray = (E[]) new Object[newlen];
601 tim 1.1 System.arraycopy(temp, 0, newArray, 0, newlen);
602     array_ = newArray;
603     return true;
604     }
605    
606     /**
607     * Appends all of the elements in the specified Collection that
608     * are not already contained in this list, to the end of
609     * this list, in the order that they are returned by the
610     * specified Collection's Iterator.
611     *
612     * @param c elements to be added into this list.
613     * @return the number of elements added
614     */
615 tim 1.7 public synchronized int addAllAbsent(Collection<? extends E> c) {
616 tim 1.1 int numNew = c.size();
617     if (numNew == 0) return 0;
618    
619     E[] elementData = array_;
620     int len = elementData.length;
621    
622 tim 1.7 E[] temp = (E[]) new Object[numNew];
623 tim 1.1 int added = 0;
624 tim 1.7 Iterator e = c.iterator();
625 tim 1.1 while (e.hasNext()) {
626 tim 1.7 E element = (E) e.next();
627 tim 1.1 if (indexOf(element, elementData, len) < 0) {
628     if (indexOf(element, temp, added) < 0) {
629     temp[added++] = element;
630     }
631     }
632     }
633    
634     if (added == 0) return 0;
635    
636 tim 1.7 E[] newArray = (E[]) new Object[len+added];
637 tim 1.1 System.arraycopy(elementData, 0, newArray, 0, len);
638     System.arraycopy(temp, 0, newArray, len, added);
639     array_ = newArray;
640     return added;
641     }
642    
643     /**
644     * Removes all of the elements from this list.
645     *
646     */
647     public synchronized void clear() {
648 tim 1.7 array_ = (E[]) new Object[0];
649 tim 1.1 }
650    
651     /**
652     * Appends all of the elements in the specified Collection to the end of
653     * this list, in the order that they are returned by the
654     * specified Collection's Iterator.
655     *
656     * @param c elements to be inserted into this list.
657 dl 1.6 * @return true if any elements are added
658 tim 1.1 */
659 tim 1.7 public synchronized boolean addAll(Collection<? extends E> c) {
660 tim 1.1 int numNew = c.size();
661     if (numNew == 0) return false;
662    
663     int len = array_.length;
664 tim 1.7 E[] newArray = (E[]) new Object[len+numNew];
665 tim 1.1 System.arraycopy(array_, 0, newArray, 0, len);
666 tim 1.7 Iterator e = c.iterator();
667 tim 1.1 for (int i=0; i<numNew; i++)
668 tim 1.7 newArray[len++] = (E) e.next();
669 tim 1.1 array_ = newArray;
670    
671     return true;
672     }
673    
674     /**
675     * Inserts all of the elements in the specified Collection into this
676     * list, starting at the specified position. Shifts the element
677     * currently at that position (if any) and any subsequent elements to
678     * the right (increases their indices). The new elements will appear
679     * in the list in the order that they are returned by the
680     * specified Collection's iterator.
681     *
682     * @param index index at which to insert first element
683     * from the specified collection.
684     * @param c elements to be inserted into this list.
685 dl 1.6 * @throws IndexOutOfBoundsException index out of range (index
686 tim 1.1 * &lt; 0 || index &gt; size()).
687 dl 1.6 * @return true if any elements are added
688 tim 1.1 */
689 tim 1.7 public synchronized boolean addAll(int index, Collection<? extends E> c) {
690 tim 1.1 int len = array_.length;
691     if (index > len || index < 0)
692     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+len);
693    
694     int numNew = c.size();
695     if (numNew == 0) return false;
696    
697 tim 1.7 E[] newArray = (E[]) new Object[len+numNew];
698 tim 1.1 System.arraycopy(array_, 0, newArray, 0, len);
699     int numMoved = len - index;
700     if (numMoved > 0)
701     System.arraycopy(array_, index, newArray, index + numNew, numMoved);
702 tim 1.7 Iterator e = c.iterator();
703 tim 1.1 for (int i=0; i<numNew; i++)
704 tim 1.7 newArray[index++] = (E) e.next();
705 tim 1.1 array_ = newArray;
706    
707     return true;
708     }
709    
710     /**
711     * Check if the given index is in range. If not, throw an appropriate
712     * runtime exception.
713     */
714     private void rangeCheck(int index, int length) {
715     if (index >= length || index < 0)
716     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+ length);
717     }
718    
719     /**
720     * Save the state of the list to a stream (i.e., serialize it).
721     *
722     * @serialData The length of the array backing the list is emitted
723     * (int), followed by all of its elements (each an Object)
724     * in the proper order.
725 dl 1.6 * @param s the stream
726 tim 1.1 */
727     private void writeObject(java.io.ObjectOutputStream s)
728     throws java.io.IOException{
729    
730     // Write out element count, and any hidden stuff
731     s.defaultWriteObject();
732    
733     E[] elementData = array();
734     // Write out array length
735     s.writeInt(elementData.length);
736    
737     // Write out all elements in the proper order.
738     for (int i=0; i<elementData.length; i++)
739     s.writeObject(elementData[i]);
740     }
741    
742     /**
743     * Reconstitute the list from a stream (i.e., deserialize it).
744 dl 1.6 * @param s the stream
745 tim 1.1 */
746     private synchronized void readObject(java.io.ObjectInputStream s)
747     throws java.io.IOException, ClassNotFoundException {
748    
749     // Read in size, and any hidden stuff
750     s.defaultReadObject();
751    
752     // Read in array length and allocate array
753     int arrayLength = s.readInt();
754 tim 1.7 E[] elementData = (E[]) new Object[arrayLength];
755 tim 1.1
756     // Read in all elements in the proper order.
757     for (int i=0; i<elementData.length; i++)
758     elementData[i] = (E) s.readObject();
759     array_ = elementData;
760     }
761    
762     /**
763     * Returns a string representation of this Collection, containing
764     * the String representation of each element.
765     */
766     public String toString() {
767     StringBuffer buf = new StringBuffer();
768     Iterator e = iterator();
769     buf.append("[");
770     int maxIndex = size() - 1;
771     for (int i = 0; i <= maxIndex; i++) {
772     buf.append(String.valueOf(e.next()));
773     if (i < maxIndex)
774     buf.append(", ");
775     }
776     buf.append("]");
777     return buf.toString();
778     }
779    
780    
781     /**
782     * Compares the specified Object with this List for equality. Returns true
783     * if and only if the specified Object is also a List, both Lists have the
784     * same size, and all corresponding pairs of elements in the two Lists are
785     * <em>equal</em>. (Two elements <code>e1</code> and <code>e2</code> are
786     * <em>equal</em> if <code>(e1==null ? e2==null : e1.equals(e2))</code>.)
787     * In other words, two Lists are defined to be equal if they contain the
788     * same elements in the same order.
789     * <p>
790     * This implementation first checks if the specified object is this
791     * List. If so, it returns true; if not, it checks if the specified
792     * object is a List. If not, it returns false; if so, it iterates over
793     * both lists, comparing corresponding pairs of elements. If any
794     * comparison returns false, this method returns false. If either
795     * Iterator runs out of elements before before the other it returns false
796     * (as the Lists are of unequal length); otherwise it returns true when
797     * the iterations complete.
798     *
799     * @param o the Object to be compared for equality with this List.
800     * @return true if the specified Object is equal to this List.
801     */
802     public boolean equals(Object o) {
803     if (o == this)
804     return true;
805     if (!(o instanceof List))
806     return false;
807    
808 tim 1.8 List<E> l2 = (List<E>)(o);
809 tim 1.1 if (size() != l2.size())
810     return false;
811    
812     ListIterator<E> e1 = listIterator();
813     ListIterator<E> e2 = l2.listIterator();
814     while(e1.hasNext()) {
815     E o1 = e1.next();
816     E o2 = e2.next();
817     if (!(o1==null ? o2==null : o1.equals(o2)))
818     return false;
819     }
820     return true;
821     }
822    
823     /**
824     * Returns the hash code value for this List.
825     * <p>
826     * This implementation uses exactly the code that is used to define
827     * the List hash function in the documentation for List.hashCode.
828     */
829     public int hashCode() {
830     int hashCode = 1;
831     Iterator<E> i = iterator();
832     while (i.hasNext()) {
833     E obj = i.next();
834     hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
835     }
836     return hashCode;
837     }
838    
839     /**
840     * Returns an Iterator over the elements contained in this collection.
841     * The iterator provides a snapshot of the state of the list
842     * when the iterator was constructed. No synchronization is
843     * needed while traversing the iterator. The iterator does
844     * <em>NOT</em> support the <code>remove</code> method.
845     */
846     public Iterator<E> iterator() {
847     return new COWIterator<E>(array(), 0);
848     }
849    
850     /**
851     * Returns an Iterator of the elements in this List (in proper sequence).
852     * The iterator provides a snapshot of the state of the list
853     * when the iterator was constructed. No synchronization is
854     * needed while traversing the iterator. The iterator does
855     * <em>NOT</em> support the <code>remove</code>, <code>set</code>,
856     * or <code>add</code> methods.
857     *
858     */
859     public ListIterator<E> listIterator() {
860     return new COWIterator<E>(array(), 0);
861     }
862    
863     /**
864     * Returns a ListIterator of the elements in this List (in proper
865     * sequence), starting at the specified position in the List. The
866     * specified index indicates the first element that would be returned by
867     * an initial call to nextElement. An initial call to previousElement
868     * would return the element with the specified index minus one.
869     * The ListIterator returned by this implementation will throw
870     * an UnsupportedOperationException in its remove, set and
871     * add methods.
872     *
873     * @param index index of first element to be returned from the
874     * ListIterator (by a call to getNext).
875 dl 1.6 * @throws IndexOutOfBoundsException index is out of range
876 tim 1.1 * (index &lt; 0 || index &gt; size()).
877     */
878     public ListIterator<E> listIterator(final int index) {
879     E[] elementData = array();
880     int len = elementData.length;
881     if (index<0 || index>len)
882     throw new IndexOutOfBoundsException("Index: "+index);
883    
884     return new COWIterator<E>(array(), index);
885     }
886    
887     private static class COWIterator<E> implements ListIterator<E> {
888    
889     /** Snapshot of the array **/
890     private final E[] array;
891    
892     /**
893     * Index of element to be returned by subsequent call to next.
894     */
895     private int cursor;
896    
897     private COWIterator(E[] elementArray, int initialCursor) {
898     array = elementArray;
899     cursor = initialCursor;
900     }
901    
902     public boolean hasNext() {
903     return cursor < array.length;
904     }
905    
906     public boolean hasPrevious() {
907     return cursor > 0;
908     }
909    
910     public E next() {
911     try {
912     return array[cursor++];
913     }
914     catch (IndexOutOfBoundsException ex) {
915     throw new NoSuchElementException();
916     }
917     }
918    
919     public E previous() {
920     try {
921     return array[--cursor];
922     } catch(IndexOutOfBoundsException e) {
923     throw new NoSuchElementException();
924     }
925     }
926    
927     public int nextIndex() {
928     return cursor;
929     }
930    
931     public int previousIndex() {
932     return cursor-1;
933     }
934    
935     /**
936     * Not supported. Always throws UnsupportedOperationException.
937 dl 1.6 * @throws UnsupportedOperationException remove is not supported
938 tim 1.1 * by this Iterator.
939     */
940    
941     public void remove() {
942     throw new UnsupportedOperationException();
943     }
944    
945     /**
946     * Not supported. Always throws UnsupportedOperationException.
947 dl 1.6 * @throws UnsupportedOperationException set is not supported
948 tim 1.1 * by this Iterator.
949     */
950     public void set(E o) {
951     throw new UnsupportedOperationException();
952     }
953    
954     /**
955     * Not supported. Always throws UnsupportedOperationException.
956 dl 1.6 * @throws UnsupportedOperationException add is not supported
957 tim 1.1 * by this Iterator.
958     */
959     public void add(E o) {
960     throw new UnsupportedOperationException();
961     }
962     }
963    
964    
965     /**
966     * Returns a view of the portion of this List between fromIndex,
967     * inclusive, and toIndex, exclusive. The returned List is backed by this
968     * List, so changes in the returned List are reflected in this List, and
969     * vice-versa. While mutative operations are supported, they are
970     * probably not very useful for CopyOnWriteArrays.
971 tim 1.9 * <p>
972 tim 1.1 * The semantics of the List returned by this method become undefined if
973     * the backing list (i.e., this List) is <i>structurally modified</i> in
974     * any way other than via the returned List. (Structural modifications are
975     * those that change the size of the List, or otherwise perturb it in such
976     * a fashion that iterations in progress may yield incorrect results.)
977     *
978     * @param fromIndex low endpoint (inclusive) of the subList.
979 dl 1.6 * @param toIndex high endpoint (exclusive) of the subList.
980 tim 1.1 * @return a view of the specified range within this List.
981 dl 1.6 * @throws IndexOutOfBoundsException Illegal endpoint index value
982 tim 1.1 * (fromIndex &lt; 0 || toIndex &gt; size || fromIndex &gt; toIndex).
983     */
984     public synchronized List<E> subList(int fromIndex, int toIndex) {
985     // synchronized since sublist ctor depends on it.
986     int len = array_.length;
987     if (fromIndex<0 || toIndex>len || fromIndex>toIndex)
988     throw new IndexOutOfBoundsException();
989     return new COWSubList<E>(this, fromIndex, toIndex);
990     }
991    
992     private static class COWSubList<E> extends AbstractList<E> {
993    
994     /*
995 dl 1.2 This class extends AbstractList merely for convenience, to
996     avoid having to define addAll, etc. This doesn't hurt, but
997     is wasteful. This class does not need or use modCount
998     mechanics in AbstractList, but does need to check for
999     concurrent modification using similar mechanics. On each
1000     operation, the array that we expect the backing list to use
1001     is checked and updated. Since we do this for all of the
1002     base operations invoked by those defined in AbstractList,
1003     all is well. While inefficient, this is not worth
1004     improving. The kinds of list operations inherited from
1005     AbstractList are are already so slow on COW sublists that
1006     adding a bit more space/time doesn't seem even noticeable.
1007 tim 1.1 */
1008    
1009     private final CopyOnWriteArrayList<E> l;
1010     private final int offset;
1011     private int size;
1012     private E[] expectedArray;
1013    
1014     private COWSubList(CopyOnWriteArrayList<E> list,
1015     int fromIndex, int toIndex) {
1016     l = list;
1017     expectedArray = l.array();
1018     offset = fromIndex;
1019     size = toIndex - fromIndex;
1020     }
1021    
1022     // only call this holding l's lock
1023     private void checkForComodification() {
1024     if (l.array_ != expectedArray)
1025     throw new ConcurrentModificationException();
1026     }
1027    
1028     // only call this holding l's lock
1029     private void rangeCheck(int index) {
1030     if (index<0 || index>=size)
1031     throw new IndexOutOfBoundsException("Index: "+index+ ",Size: "+size);
1032     }
1033    
1034    
1035     public E set(int index, E element) {
1036     synchronized(l) {
1037     rangeCheck(index);
1038     checkForComodification();
1039     E x = l.set(index+offset, element);
1040     expectedArray = l.array_;
1041     return x;
1042     }
1043     }
1044    
1045     public E get(int index) {
1046     synchronized(l) {
1047     rangeCheck(index);
1048     checkForComodification();
1049     return l.get(index+offset);
1050     }
1051     }
1052    
1053     public int size() {
1054     synchronized(l) {
1055     checkForComodification();
1056     return size;
1057     }
1058     }
1059    
1060     public void add(int index, E element) {
1061     synchronized(l) {
1062     checkForComodification();
1063     if (index<0 || index>size)
1064     throw new IndexOutOfBoundsException();
1065     l.add(index+offset, element);
1066     expectedArray = l.array_;
1067     size++;
1068     }
1069     }
1070    
1071     public E remove(int index) {
1072     synchronized(l) {
1073     rangeCheck(index);
1074     checkForComodification();
1075     E result = l.remove(index+offset);
1076     expectedArray = l.array_;
1077     size--;
1078     return result;
1079     }
1080     }
1081    
1082     public Iterator<E> iterator() {
1083     synchronized(l) {
1084     checkForComodification();
1085 tim 1.8 return new COWSubListIterator<E>(l, 0, offset, size);
1086 tim 1.1 }
1087     }
1088    
1089     public ListIterator<E> listIterator(final int index) {
1090     synchronized(l) {
1091     checkForComodification();
1092     if (index<0 || index>size)
1093     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
1094 tim 1.8 return new COWSubListIterator<E>(l, index, offset, size);
1095 tim 1.1 }
1096     }
1097    
1098 tim 1.7 public List<E> subList(int fromIndex, int toIndex) {
1099     synchronized(l) {
1100     checkForComodification();
1101     if (fromIndex<0 || toIndex>size)
1102     throw new IndexOutOfBoundsException();
1103     return new COWSubList<E>(l, fromIndex+offset, toIndex+offset);
1104 tim 1.1 }
1105 tim 1.7 }
1106 tim 1.1
1107 tim 1.7 }
1108 tim 1.1
1109    
1110 tim 1.7 private static class COWSubListIterator<E> implements ListIterator<E> {
1111     private final ListIterator<E> i;
1112     private final int index;
1113     private final int offset;
1114     private final int size;
1115     private COWSubListIterator(List<E> l, int index, int offset, int size) {
1116     this.index = index;
1117     this.offset = offset;
1118     this.size = size;
1119     i = l.listIterator(index+offset);
1120     }
1121 tim 1.1
1122 tim 1.7 public boolean hasNext() {
1123     return nextIndex() < size;
1124     }
1125 tim 1.1
1126 tim 1.7 public E next() {
1127     if (hasNext())
1128     return i.next();
1129     else
1130     throw new NoSuchElementException();
1131     }
1132 tim 1.1
1133 tim 1.7 public boolean hasPrevious() {
1134     return previousIndex() >= 0;
1135     }
1136 tim 1.1
1137 tim 1.7 public E previous() {
1138     if (hasPrevious())
1139     return i.previous();
1140     else
1141     throw new NoSuchElementException();
1142     }
1143 tim 1.1
1144 tim 1.7 public int nextIndex() {
1145     return i.nextIndex() - offset;
1146     }
1147 tim 1.1
1148 tim 1.7 public int previousIndex() {
1149     return i.previousIndex() - offset;
1150 tim 1.1 }
1151    
1152 tim 1.7 public void remove() {
1153     throw new UnsupportedOperationException();
1154     }
1155 tim 1.1
1156 tim 1.7 public void set(E o) {
1157     throw new UnsupportedOperationException();
1158 tim 1.1 }
1159    
1160 tim 1.7 public void add(E o) {
1161     throw new UnsupportedOperationException();
1162     }
1163 tim 1.1 }
1164    
1165     }