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