ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.2
Committed: Tue May 27 18:14:39 2003 UTC (21 years ago) by dl
Branch: MAIN
CVS Tags: JSR166_PRERELEASE_0_1
Changes since 1.1: +22 -23 lines
Log Message:
re-check-in initial implementations

File Contents

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