ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.11
Committed: Mon Aug 25 19:27:58 2003 UTC (20 years, 9 months ago) by dl
Branch: MAIN
Changes since 1.10: +1 -0 lines
Log Message:
serialVersionUIDs

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