ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.29
Committed: Mon Mar 7 23:49:21 2005 UTC (19 years, 2 months ago) by dl
Branch: MAIN
Changes since 1.28: +8 -8 lines
Log Message:
Javadoc improvements

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 thread-safe 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.
24 *
25 * <p> 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 if 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 if 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 if 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 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.
826 *
827 * <p> This implementation uses the definition in {@link
828 * List#hashCode}.
829 * @return the hash code
830 */
831 public int hashCode() {
832 int hashCode = 1;
833 Iterator<E> i = iterator();
834 while (i.hasNext()) {
835 E obj = i.next();
836 hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
837 }
838 return hashCode;
839 }
840
841 /**
842 * Returns an Iterator over the elements contained in this collection.
843 * The iterator provides a snapshot of the state of the list
844 * when the iterator was constructed. No synchronization is
845 * needed while traversing the iterator. The iterator does
846 * <em>NOT</em> support the <tt>remove</tt> method.
847 * @return the iterator
848 */
849 public Iterator<E> iterator() {
850 return new COWIterator<E>(array(), 0);
851 }
852
853 /**
854 * Returns an Iterator of the elements in this List (in proper sequence).
855 * The iterator provides a snapshot of the state of the list
856 * when the iterator was constructed. No synchronization is
857 * needed while traversing the iterator. The iterator does
858 * <em>NOT</em> support the <tt>remove</tt>, <tt>set</tt>,
859 * or <tt>add</tt> methods.
860 * @return the iterator
861 *
862 */
863 public ListIterator<E> listIterator() {
864 return new COWIterator<E>(array(), 0);
865 }
866
867 /**
868 * Returns a ListIterator of the elements in this List (in proper
869 * sequence), starting at the specified position in the List. The
870 * specified index indicates the first element that would be returned by
871 * an initial call to nextElement. An initial call to previousElement
872 * would return the element with the specified index minus one.
873 * The ListIterator returned by this implementation will throw
874 * an UnsupportedOperationException in its remove, set and
875 * add methods.
876 *
877 * @param index index of first element to be returned from the
878 * ListIterator (by a call to getNext).
879 * @return the iterator
880 * @throws IndexOutOfBoundsException if index is out of range
881 * (index &lt; 0 || index &gt; size()).
882 */
883 public ListIterator<E> listIterator(final int index) {
884 E[] elementData = array();
885 int len = elementData.length;
886 if (index<0 || index>len)
887 throw new IndexOutOfBoundsException("Index: "+index);
888
889 return new COWIterator<E>(array(), index);
890 }
891
892 private static class COWIterator<E> implements ListIterator<E> {
893
894 /** Snapshot of the array **/
895 private final E[] array;
896
897 /**
898 * Index of element to be returned by subsequent call to next.
899 */
900 private int cursor;
901
902 private COWIterator(E[] elementArray, int initialCursor) {
903 array = elementArray;
904 cursor = initialCursor;
905 }
906
907 public boolean hasNext() {
908 return cursor < array.length;
909 }
910
911 public boolean hasPrevious() {
912 return cursor > 0;
913 }
914
915 public E next() {
916 try {
917 return array[cursor++];
918 } catch (IndexOutOfBoundsException ex) {
919 throw new NoSuchElementException();
920 }
921 }
922
923 public E previous() {
924 try {
925 return array[--cursor];
926 } catch(IndexOutOfBoundsException e) {
927 throw new NoSuchElementException();
928 }
929 }
930
931 public int nextIndex() {
932 return cursor;
933 }
934
935 public int previousIndex() {
936 return cursor-1;
937 }
938
939 /**
940 * Not supported. Always throws UnsupportedOperationException.
941 * @throws UnsupportedOperationException always; remove is not supported
942 * by this Iterator.
943 */
944
945 public void remove() {
946 throw new UnsupportedOperationException();
947 }
948
949 /**
950 * Not supported. Always throws UnsupportedOperationException.
951 * @throws UnsupportedOperationException always; set is not supported
952 * by this Iterator.
953 */
954 public void set(E o) {
955 throw new UnsupportedOperationException();
956 }
957
958 /**
959 * Not supported. Always throws UnsupportedOperationException.
960 * @throws UnsupportedOperationException always; add is not supported
961 * by this Iterator.
962 */
963 public void add(E o) {
964 throw new UnsupportedOperationException();
965 }
966 }
967
968
969 /**
970 * Returns a view of the portion of this List between fromIndex,
971 * inclusive, and toIndex, exclusive. The returned List is backed by this
972 * List, so changes in the returned List are reflected in this List, and
973 * vice-versa. While mutative operations are supported, they are
974 * probably not very useful for CopyOnWriteArrayLists.
975 * <p>
976 * The semantics of the List returned by this method become undefined if
977 * the backing list (i.e., this List) is <i>structurally modified</i> in
978 * any way other than via the returned List. (Structural modifications are
979 * those that change the size of the List, or otherwise perturb it in such
980 * a fashion that iterations in progress may yield incorrect results.)
981 *
982 * @param fromIndex low endpoint (inclusive) of the subList.
983 * @param toIndex high endpoint (exclusive) of the subList.
984 * @return a view of the specified range within this List.
985 * @throws IndexOutOfBoundsException if
986 * (fromIndex &lt; 0 || toIndex &gt; size || fromIndex &gt; toIndex).
987 */
988 public synchronized List<E> subList(int fromIndex, int toIndex) {
989 // synchronized since sublist constructor depends on it.
990 int len = array.length;
991 if (fromIndex<0 || toIndex>len || fromIndex>toIndex)
992 throw new IndexOutOfBoundsException();
993 return new COWSubList<E>(this, fromIndex, toIndex);
994 }
995
996 private static class COWSubList<E> extends AbstractList<E> {
997
998 /*
999 This class extends AbstractList merely for convenience, to
1000 avoid having to define addAll, etc. This doesn't hurt, but
1001 is wasteful. This class does not need or use modCount
1002 mechanics in AbstractList, but does need to check for
1003 concurrent modification using similar mechanics. On each
1004 operation, the array that we expect the backing list to use
1005 is checked and updated. Since we do this for all of the
1006 base operations invoked by those defined in AbstractList,
1007 all is well. While inefficient, this is not worth
1008 improving. The kinds of list operations inherited from
1009 AbstractList are already so slow on COW sublists that
1010 adding a bit more space/time doesn't seem even noticeable.
1011 */
1012
1013 private final CopyOnWriteArrayList<E> l;
1014 private final int offset;
1015 private int size;
1016 private E[] expectedArray;
1017
1018 private COWSubList(CopyOnWriteArrayList<E> list,
1019 int fromIndex, int toIndex) {
1020 l = list;
1021 expectedArray = l.array();
1022 offset = fromIndex;
1023 size = toIndex - fromIndex;
1024 }
1025
1026 // only call this holding l's lock
1027 private void checkForComodification() {
1028 if (l.array != expectedArray)
1029 throw new ConcurrentModificationException();
1030 }
1031
1032 // only call this holding l's lock
1033 private void rangeCheck(int index) {
1034 if (index<0 || index>=size)
1035 throw new IndexOutOfBoundsException("Index: "+index+ ",Size: "+size);
1036 }
1037
1038
1039 public E set(int index, E element) {
1040 synchronized(l) {
1041 rangeCheck(index);
1042 checkForComodification();
1043 E x = l.set(index+offset, element);
1044 expectedArray = l.array;
1045 return x;
1046 }
1047 }
1048
1049 public E get(int index) {
1050 synchronized(l) {
1051 rangeCheck(index);
1052 checkForComodification();
1053 return l.get(index+offset);
1054 }
1055 }
1056
1057 public int size() {
1058 synchronized(l) {
1059 checkForComodification();
1060 return size;
1061 }
1062 }
1063
1064 public void add(int index, E element) {
1065 synchronized(l) {
1066 checkForComodification();
1067 if (index<0 || index>size)
1068 throw new IndexOutOfBoundsException();
1069 l.add(index+offset, element);
1070 expectedArray = l.array;
1071 size++;
1072 }
1073 }
1074
1075 public void clear() {
1076 synchronized(l) {
1077 checkForComodification();
1078 l.removeRange(offset, offset+size);
1079 expectedArray = l.array;
1080 size = 0;
1081 }
1082 }
1083
1084 public E remove(int index) {
1085 synchronized(l) {
1086 rangeCheck(index);
1087 checkForComodification();
1088 E result = l.remove(index+offset);
1089 expectedArray = l.array;
1090 size--;
1091 return result;
1092 }
1093 }
1094
1095 public Iterator<E> iterator() {
1096 synchronized(l) {
1097 checkForComodification();
1098 return new COWSubListIterator<E>(l, 0, offset, size);
1099 }
1100 }
1101
1102 public ListIterator<E> listIterator(final int index) {
1103 synchronized(l) {
1104 checkForComodification();
1105 if (index<0 || index>size)
1106 throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
1107 return new COWSubListIterator<E>(l, index, offset, size);
1108 }
1109 }
1110
1111 public List<E> subList(int fromIndex, int toIndex) {
1112 synchronized(l) {
1113 checkForComodification();
1114 if (fromIndex<0 || toIndex>size)
1115 throw new IndexOutOfBoundsException();
1116 return new COWSubList<E>(l, fromIndex+offset, toIndex+offset);
1117 }
1118 }
1119
1120 }
1121
1122
1123 private static class COWSubListIterator<E> implements ListIterator<E> {
1124 private final ListIterator<E> i;
1125 private final int index;
1126 private final int offset;
1127 private final int size;
1128 private COWSubListIterator(List<E> l, int index, int offset, int size) {
1129 this.index = index;
1130 this.offset = offset;
1131 this.size = size;
1132 i = l.listIterator(index+offset);
1133 }
1134
1135 public boolean hasNext() {
1136 return nextIndex() < size;
1137 }
1138
1139 public E next() {
1140 if (hasNext())
1141 return i.next();
1142 else
1143 throw new NoSuchElementException();
1144 }
1145
1146 public boolean hasPrevious() {
1147 return previousIndex() >= 0;
1148 }
1149
1150 public E previous() {
1151 if (hasPrevious())
1152 return i.previous();
1153 else
1154 throw new NoSuchElementException();
1155 }
1156
1157 public int nextIndex() {
1158 return i.nextIndex() - offset;
1159 }
1160
1161 public int previousIndex() {
1162 return i.previousIndex() - offset;
1163 }
1164
1165 public void remove() {
1166 throw new UnsupportedOperationException();
1167 }
1168
1169 public void set(E o) {
1170 throw new UnsupportedOperationException();
1171 }
1172
1173 public void add(E o) {
1174 throw new UnsupportedOperationException();
1175 }
1176 }
1177
1178 }