ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.4
Committed: Sat Jun 7 18:20:20 2003 UTC (21 years ago) by dl
Branch: MAIN
CVS Tags: JSR166_PRELIMINARY_TEST_RELEASE_1
Changes since 1.3: +10 -11 lines
Log Message:
Misc documentation updates

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