ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.33
Committed: Mon May 2 08:35:49 2005 UTC (19 years, 1 month ago) by jsr166
Branch: MAIN
Changes since 1.32: +4 -4 lines
Log Message:
E o -> E e

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