ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.2
Committed: Tue May 27 18:14:39 2003 UTC (21 years ago) by dl
Branch: MAIN
CVS Tags: JSR166_PRERELEASE_0_1
Changes since 1.1: +22 -23 lines
Log Message:
re-check-in initial implementations

File Contents

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