ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.3
Committed: Fri Jun 6 16:53:04 2003 UTC (21 years ago) by dl
Branch: MAIN
Changes since 1.2: +12 -2 lines
Log Message:
Minor doc updates; FairReentrantLock serialize now

File Contents

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