ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.1
Committed: Wed May 14 21:30:46 2003 UTC (21 years, 1 month ago) by tim
Branch: MAIN
Log Message:
Moved main source rooted at . to ./src/main
Moved test source rooted at ./etc/testcases to ./src/test

File Contents

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