ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.4
Committed: Sat Jun 7 18:20:20 2003 UTC (21 years ago) by dl
Branch: MAIN
CVS Tags: JSR166_PRELIMINARY_TEST_RELEASE_1
Changes since 1.3: +10 -11 lines
Log Message:
Misc documentation updates

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