ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.5
Committed: Mon Jun 23 02:26:16 2003 UTC (20 years, 11 months ago) by brian
Branch: MAIN
Changes since 1.4: +4 -3 lines
Log Message:
Partial javadoc pass

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