ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.40
Committed: Tue May 31 13:56:31 2005 UTC (19 years ago) by dl
Branch: MAIN
Changes since 1.39: +352 -337 lines
Log Message:
Use anticipated Arrays.clone methods

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