ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.25
Committed: Mon Feb 9 00:23:55 2004 UTC (20 years, 4 months ago) by dl
Branch: MAIN
Changes since 1.24: +5 -6 lines
Log Message:
Wording improvements and fixes

File Contents

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