ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.8
Committed: Thu Jul 31 16:49:32 2003 UTC (20 years, 10 months ago) by tim
Branch: MAIN
Changes since 1.7: +4 -4 lines
Log Message:
Fix unchecked calls to raw type

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