32 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A. |
31 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A. |
33 * All rights reserved. |
32 * All rights reserved. |
34 */ |
33 */ |
35 |
34 |
36 package java.util.concurrent; |
35 package java.util.concurrent; |
37 import java.util.*; |
36 import java.util.AbstractList; |
|
37 import java.util.Arrays; |
|
38 import java.util.Collection; |
|
39 import java.util.Comparator; |
|
40 import java.util.ConcurrentModificationException; |
|
41 import java.util.Iterator; |
|
42 import java.util.List; |
|
43 import java.util.ListIterator; |
|
44 import java.util.NoSuchElementException; |
|
45 import java.util.Objects; |
|
46 import java.util.RandomAccess; |
|
47 import java.util.Spliterator; |
|
48 import java.util.Spliterators; |
38 import java.util.concurrent.locks.ReentrantLock; |
49 import java.util.concurrent.locks.ReentrantLock; |
39 import java.util.function.Consumer; |
50 import java.util.function.Consumer; |
40 import java.util.function.Predicate; |
51 import java.util.function.Predicate; |
41 import java.util.function.UnaryOperator; |
52 import java.util.function.UnaryOperator; |
42 |
53 |
43 /** |
54 /** |
44 * A thread-safe variant of {@link java.util.ArrayList} in which all mutative |
55 * A thread-safe variant of {@link java.util.ArrayList} in which all mutative |
45 * operations (<tt>add</tt>, <tt>set</tt>, and so on) are implemented by |
56 * operations ({@code add}, {@code set}, and so on) are implemented by |
46 * making a fresh copy of the underlying array. |
57 * making a fresh copy of the underlying array. |
47 * |
58 * |
48 * <p> This is ordinarily too costly, but may be <em>more</em> efficient |
59 * <p>This is ordinarily too costly, but may be <em>more</em> efficient |
49 * than alternatives when traversal operations vastly outnumber |
60 * than alternatives when traversal operations vastly outnumber |
50 * mutations, and is useful when you cannot or don't want to |
61 * mutations, and is useful when you cannot or don't want to |
51 * synchronize traversals, yet need to preclude interference among |
62 * synchronize traversals, yet need to preclude interference among |
52 * concurrent threads. The "snapshot" style iterator method uses a |
63 * concurrent threads. The "snapshot" style iterator method uses a |
53 * reference to the state of the array at the point that the iterator |
64 * reference to the state of the array at the point that the iterator |
54 * was created. This array never changes during the lifetime of the |
65 * was created. This array never changes during the lifetime of the |
55 * iterator, so interference is impossible and the iterator is |
66 * iterator, so interference is impossible and the iterator is |
56 * guaranteed not to throw <tt>ConcurrentModificationException</tt>. |
67 * guaranteed not to throw {@code ConcurrentModificationException}. |
57 * The iterator will not reflect additions, removals, or changes to |
68 * The iterator will not reflect additions, removals, or changes to |
58 * the list since the iterator was created. Element-changing |
69 * the list since the iterator was created. Element-changing |
59 * operations on iterators themselves (<tt>remove</tt>, <tt>set</tt>, and |
70 * operations on iterators themselves ({@code remove}, {@code set}, and |
60 * <tt>add</tt>) are not supported. These methods throw |
71 * {@code add}) are not supported. These methods throw |
61 * <tt>UnsupportedOperationException</tt>. |
72 * {@code UnsupportedOperationException}. |
62 * |
73 * |
63 * <p>All elements are permitted, including <tt>null</tt>. |
74 * <p>All elements are permitted, including {@code null}. |
64 * |
75 * |
65 * <p>Memory consistency effects: As with other concurrent |
76 * <p>Memory consistency effects: As with other concurrent |
66 * collections, actions in a thread prior to placing an object into a |
77 * collections, actions in a thread prior to placing an object into a |
67 * {@code CopyOnWriteArrayList} |
78 * {@code CopyOnWriteArrayList} |
68 * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a> |
79 * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a> |
226 return indexOf(o, elements, 0, elements.length); |
242 return indexOf(o, elements, 0, elements.length); |
227 } |
243 } |
228 |
244 |
229 /** |
245 /** |
230 * Returns the index of the first occurrence of the specified element in |
246 * Returns the index of the first occurrence of the specified element in |
231 * this list, searching forwards from <tt>index</tt>, or returns -1 if |
247 * this list, searching forwards from {@code index}, or returns -1 if |
232 * the element is not found. |
248 * the element is not found. |
233 * More formally, returns the lowest index <tt>i</tt> such that |
249 * More formally, returns the lowest index {@code i} such that |
234 * <tt>(i >= index && (e==null ? get(i)==null : e.equals(get(i))))</tt>, |
250 * <tt>(i >= index && (e==null ? get(i)==null : e.equals(get(i))))</tt>, |
235 * or -1 if there is no such index. |
251 * or -1 if there is no such index. |
236 * |
252 * |
237 * @param e element to search for |
253 * @param e element to search for |
238 * @param index index to start searching from |
254 * @param index index to start searching from |
239 * @return the index of the first occurrence of the element in |
255 * @return the index of the first occurrence of the element in |
240 * this list at position <tt>index</tt> or later in the list; |
256 * this list at position {@code index} or later in the list; |
241 * <tt>-1</tt> if the element is not found. |
257 * {@code -1} if the element is not found. |
242 * @throws IndexOutOfBoundsException if the specified index is negative |
258 * @throws IndexOutOfBoundsException if the specified index is negative |
243 */ |
259 */ |
244 public int indexOf(E e, int index) { |
260 public int indexOf(E e, int index) { |
245 Object[] elements = getArray(); |
261 Object[] elements = getArray(); |
246 return indexOf(e, elements, index, elements.length); |
262 return indexOf(e, elements, index, elements.length); |
254 return lastIndexOf(o, elements, elements.length - 1); |
270 return lastIndexOf(o, elements, elements.length - 1); |
255 } |
271 } |
256 |
272 |
257 /** |
273 /** |
258 * Returns the index of the last occurrence of the specified element in |
274 * Returns the index of the last occurrence of the specified element in |
259 * this list, searching backwards from <tt>index</tt>, or returns -1 if |
275 * this list, searching backwards from {@code index}, or returns -1 if |
260 * the element is not found. |
276 * the element is not found. |
261 * More formally, returns the highest index <tt>i</tt> such that |
277 * More formally, returns the highest index {@code i} such that |
262 * <tt>(i <= index && (e==null ? get(i)==null : e.equals(get(i))))</tt>, |
278 * <tt>(i <= index && (e==null ? get(i)==null : e.equals(get(i))))</tt>, |
263 * or -1 if there is no such index. |
279 * or -1 if there is no such index. |
264 * |
280 * |
265 * @param e element to search for |
281 * @param e element to search for |
266 * @param index index to start searching backwards from |
282 * @param index index to start searching backwards from |
267 * @return the index of the last occurrence of the element at position |
283 * @return the index of the last occurrence of the element at position |
268 * less than or equal to <tt>index</tt> in this list; |
284 * less than or equal to {@code index} in this list; |
269 * -1 if the element is not found. |
285 * -1 if the element is not found. |
270 * @throws IndexOutOfBoundsException if the specified index is greater |
286 * @throws IndexOutOfBoundsException if the specified index is greater |
271 * than or equal to the current size of this list |
287 * than or equal to the current size of this list |
272 */ |
288 */ |
273 public int lastIndexOf(E e, int index) { |
289 public int lastIndexOf(E e, int index) { |
321 * the size of this list. |
337 * the size of this list. |
322 * |
338 * |
323 * <p>If this list fits in the specified array with room to spare |
339 * <p>If this list fits in the specified array with room to spare |
324 * (i.e., the array has more elements than this list), the element in |
340 * (i.e., the array has more elements than this list), the element in |
325 * the array immediately following the end of the list is set to |
341 * the array immediately following the end of the list is set to |
326 * <tt>null</tt>. (This is useful in determining the length of this |
342 * {@code null}. (This is useful in determining the length of this |
327 * list <i>only</i> if the caller knows that this list does not contain |
343 * list <i>only</i> if the caller knows that this list does not contain |
328 * any null elements.) |
344 * any null elements.) |
329 * |
345 * |
330 * <p>Like the {@link #toArray()} method, this method acts as bridge between |
346 * <p>Like the {@link #toArray()} method, this method acts as bridge between |
331 * array-based and collection-based APIs. Further, this method allows |
347 * array-based and collection-based APIs. Further, this method allows |
332 * precise control over the runtime type of the output array, and may, |
348 * precise control over the runtime type of the output array, and may, |
333 * under certain circumstances, be used to save allocation costs. |
349 * under certain circumstances, be used to save allocation costs. |
334 * |
350 * |
335 * <p>Suppose <tt>x</tt> is a list known to contain only strings. |
351 * <p>Suppose {@code x} is a list known to contain only strings. |
336 * The following code can be used to dump the list into a newly |
352 * The following code can be used to dump the list into a newly |
337 * allocated array of <tt>String</tt>: |
353 * allocated array of {@code String}: |
338 * |
354 * |
339 * <pre> {@code String[] y = x.toArray(new String[0]);}</pre> |
355 * <pre> {@code String[] y = x.toArray(new String[0]);}</pre> |
340 * |
356 * |
341 * Note that <tt>toArray(new Object[0])</tt> is identical in function to |
357 * Note that {@code toArray(new Object[0])} is identical in function to |
342 * <tt>toArray()</tt>. |
358 * {@code toArray()}. |
343 * |
359 * |
344 * @param a the array into which the elements of the list are to |
360 * @param a the array into which the elements of the list are to |
345 * be stored, if it is big enough; otherwise, a new array of the |
361 * be stored, if it is big enough; otherwise, a new array of the |
346 * same runtime type is allocated for this purpose. |
362 * same runtime type is allocated for this purpose. |
347 * @return an array containing all the elements in this list |
363 * @return an array containing all the elements in this list |
494 |
510 |
495 /** |
511 /** |
496 * Removes the first occurrence of the specified element from this list, |
512 * Removes the first occurrence of the specified element from this list, |
497 * if it is present. If this list does not contain the element, it is |
513 * if it is present. If this list does not contain the element, it is |
498 * unchanged. More formally, removes the element with the lowest index |
514 * unchanged. More formally, removes the element with the lowest index |
499 * <tt>i</tt> such that |
515 * {@code i} such that |
500 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> |
516 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> |
501 * (if such an element exists). Returns <tt>true</tt> if this list |
517 * (if such an element exists). Returns {@code true} if this list |
502 * contained the specified element (or equivalently, if this list |
518 * contained the specified element (or equivalently, if this list |
503 * changed as a result of the call). |
519 * changed as a result of the call). |
504 * |
520 * |
505 * @param o element to be removed from this list, if present |
521 * @param o element to be removed from this list, if present |
506 * @return <tt>true</tt> if this list contained the specified element |
522 * @return {@code true} if this list contained the specified element |
507 */ |
523 */ |
508 public boolean remove(Object o) { |
524 public boolean remove(Object o) { |
|
525 Object[] snapshot = getArray(); |
|
526 int index = indexOf(o, snapshot, 0, snapshot.length); |
|
527 return (index < 0) ? false : remove(o, snapshot, index); |
|
528 } |
|
529 |
|
530 /** |
|
531 * A version of remove(Object) using the strong hint that given |
|
532 * recent snapshot contains o at the given index. |
|
533 */ |
|
534 private boolean remove(Object o, Object[] snapshot, int index) { |
509 final ReentrantLock lock = this.lock; |
535 final ReentrantLock lock = this.lock; |
510 lock.lock(); |
536 lock.lock(); |
511 try { |
537 try { |
512 Object[] elements = getArray(); |
538 Object[] current = getArray(); |
513 int len = elements.length; |
539 int len = current.length; |
514 if (len != 0) { |
540 if (snapshot != current) findIndex: { |
515 // Copy while searching for element to remove |
541 int prefix = Math.min(index, len); |
516 // This wins in the normal case of element being present |
542 for (int i = 0; i < prefix; i++) { |
517 int newlen = len - 1; |
543 if (current[i] != snapshot[i] && eq(o, current[i])) { |
518 Object[] newElements = new Object[newlen]; |
544 index = i; |
519 |
545 break findIndex; |
520 for (int i = 0; i < newlen; ++i) { |
546 } |
521 if (eq(o, elements[i])) { |
|
522 // found one; copy remaining and exit |
|
523 for (int k = i + 1; k < len; ++k) |
|
524 newElements[k-1] = elements[k]; |
|
525 setArray(newElements); |
|
526 return true; |
|
527 } else |
|
528 newElements[i] = elements[i]; |
|
529 } |
547 } |
530 |
548 if (index >= len) |
531 // special handling for last cell |
549 return false; |
532 if (eq(o, elements[newlen])) { |
550 if (current[index] == o) |
533 setArray(newElements); |
551 break findIndex; |
534 return true; |
552 index = indexOf(o, current, index, len); |
535 } |
553 if (index < 0) |
536 } |
554 return false; |
537 return false; |
555 } |
|
556 Object[] newElements = new Object[len - 1]; |
|
557 System.arraycopy(current, 0, newElements, 0, index); |
|
558 System.arraycopy(current, index + 1, |
|
559 newElements, index, |
|
560 len - index - 1); |
|
561 setArray(newElements); |
|
562 return true; |
538 } finally { |
563 } finally { |
539 lock.unlock(); |
564 lock.unlock(); |
540 } |
565 } |
541 } |
566 } |
542 |
567 |
543 /** |
568 /** |
544 * Removes from this list all of the elements whose index is between |
569 * Removes from this list all of the elements whose index is between |
545 * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive. |
570 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. |
546 * Shifts any succeeding elements to the left (reduces their index). |
571 * Shifts any succeeding elements to the left (reduces their index). |
547 * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements. |
572 * This call shortens the list by {@code (toIndex - fromIndex)} elements. |
548 * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.) |
573 * (If {@code toIndex==fromIndex}, this operation has no effect.) |
549 * |
574 * |
550 * @param fromIndex index of first element to be removed |
575 * @param fromIndex index of first element to be removed |
551 * @param toIndex index after last element to be removed |
576 * @param toIndex index after last element to be removed |
552 * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range |
577 * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range |
553 * ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex}) |
578 * ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex}) |
579 |
604 |
580 /** |
605 /** |
581 * Appends the element, if not present. |
606 * Appends the element, if not present. |
582 * |
607 * |
583 * @param e element to be added to this list, if absent |
608 * @param e element to be added to this list, if absent |
584 * @return <tt>true</tt> if the element was added |
609 * @return {@code true} if the element was added |
585 */ |
610 */ |
586 public boolean addIfAbsent(E e) { |
611 public boolean addIfAbsent(E e) { |
|
612 Object[] snapshot = getArray(); |
|
613 return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false : |
|
614 addIfAbsent(e, snapshot); |
|
615 } |
|
616 |
|
617 /** |
|
618 * A version of addIfAbsent using the strong hint that given |
|
619 * recent snapshot does not contain e. |
|
620 */ |
|
621 private boolean addIfAbsent(E e, Object[] snapshot) { |
587 final ReentrantLock lock = this.lock; |
622 final ReentrantLock lock = this.lock; |
588 lock.lock(); |
623 lock.lock(); |
589 try { |
624 try { |
590 // Copy while checking if already present. |
625 Object[] current = getArray(); |
591 // This wins in the most common case where it is not present |
626 int len = current.length; |
592 Object[] elements = getArray(); |
627 if (snapshot != current) { |
593 int len = elements.length; |
628 // Optimize for lost race to another addXXX operation |
594 Object[] newElements = new Object[len + 1]; |
629 int common = Math.min(snapshot.length, len); |
595 for (int i = 0; i < len; ++i) { |
630 for (int i = 0; i < common; i++) |
596 if (eq(e, elements[i])) |
631 if (current[i] != snapshot[i] && eq(e, current[i])) |
597 return false; // exit, throwing away copy |
632 return false; |
598 else |
633 if (indexOf(e, current, common, len) >= 0) |
599 newElements[i] = elements[i]; |
634 return false; |
600 } |
635 } |
|
636 Object[] newElements = Arrays.copyOf(current, len + 1); |
601 newElements[len] = e; |
637 newElements[len] = e; |
602 setArray(newElements); |
638 setArray(newElements); |
603 return true; |
639 return true; |
604 } finally { |
640 } finally { |
605 lock.unlock(); |
641 lock.unlock(); |
606 } |
642 } |
607 } |
643 } |
608 |
644 |
609 /** |
645 /** |
610 * Returns <tt>true</tt> if this list contains all of the elements of the |
646 * Returns {@code true} if this list contains all of the elements of the |
611 * specified collection. |
647 * specified collection. |
612 * |
648 * |
613 * @param c collection to be checked for containment in this list |
649 * @param c collection to be checked for containment in this list |
614 * @return <tt>true</tt> if this list contains all of the elements of the |
650 * @return {@code true} if this list contains all of the elements of the |
615 * specified collection |
651 * specified collection |
616 * @throws NullPointerException if the specified collection is null |
652 * @throws NullPointerException if the specified collection is null |
617 * @see #contains(Object) |
653 * @see #contains(Object) |
618 */ |
654 */ |
619 public boolean containsAll(Collection<?> c) { |
655 public boolean containsAll(Collection<?> c) { |
725 */ |
761 */ |
726 public int addAllAbsent(Collection<? extends E> c) { |
762 public int addAllAbsent(Collection<? extends E> c) { |
727 Object[] cs = c.toArray(); |
763 Object[] cs = c.toArray(); |
728 if (cs.length == 0) |
764 if (cs.length == 0) |
729 return 0; |
765 return 0; |
730 Object[] uniq = new Object[cs.length]; |
|
731 final ReentrantLock lock = this.lock; |
766 final ReentrantLock lock = this.lock; |
732 lock.lock(); |
767 lock.lock(); |
733 try { |
768 try { |
734 Object[] elements = getArray(); |
769 Object[] elements = getArray(); |
735 int len = elements.length; |
770 int len = elements.length; |
736 int added = 0; |
771 int added = 0; |
737 for (int i = 0; i < cs.length; ++i) { // scan for duplicates |
772 // uniquify and compact elements in cs |
|
773 for (int i = 0; i < cs.length; ++i) { |
738 Object e = cs[i]; |
774 Object e = cs[i]; |
739 if (indexOf(e, elements, 0, len) < 0 && |
775 if (indexOf(e, elements, 0, len) < 0 && |
740 indexOf(e, uniq, 0, added) < 0) |
776 indexOf(e, cs, 0, added) < 0) |
741 uniq[added++] = e; |
777 cs[added++] = e; |
742 } |
778 } |
743 if (added > 0) { |
779 if (added > 0) { |
744 Object[] newElements = Arrays.copyOf(elements, len + added); |
780 Object[] newElements = Arrays.copyOf(elements, len + added); |
745 System.arraycopy(uniq, 0, newElements, len, added); |
781 System.arraycopy(cs, 0, newElements, len, added); |
746 setArray(newElements); |
782 setArray(newElements); |
747 } |
783 } |
748 return added; |
784 return added; |
749 } finally { |
785 } finally { |
750 lock.unlock(); |
786 lock.unlock(); |
769 * Appends all of the elements in the specified collection to the end |
805 * Appends all of the elements in the specified collection to the end |
770 * of this list, in the order that they are returned by the specified |
806 * of this list, in the order that they are returned by the specified |
771 * collection's iterator. |
807 * collection's iterator. |
772 * |
808 * |
773 * @param c collection containing elements to be added to this list |
809 * @param c collection containing elements to be added to this list |
774 * @return <tt>true</tt> if this list changed as a result of the call |
810 * @return {@code true} if this list changed as a result of the call |
775 * @throws NullPointerException if the specified collection is null |
811 * @throws NullPointerException if the specified collection is null |
776 * @see #add(Object) |
812 * @see #add(Object) |
777 */ |
813 */ |
778 public boolean addAll(Collection<? extends E> c) { |
814 public boolean addAll(Collection<? extends E> c) { |
779 Object[] cs = c.toArray(); |
815 Object[] cs = (c.getClass() == CopyOnWriteArrayList.class) ? |
|
816 ((CopyOnWriteArrayList<?>)c).getArray() : c.toArray(); |
780 if (cs.length == 0) |
817 if (cs.length == 0) |
781 return false; |
818 return false; |
782 final ReentrantLock lock = this.lock; |
819 final ReentrantLock lock = this.lock; |
783 lock.lock(); |
820 lock.lock(); |
784 try { |
821 try { |
785 Object[] elements = getArray(); |
822 Object[] elements = getArray(); |
786 int len = elements.length; |
823 int len = elements.length; |
787 Object[] newElements = Arrays.copyOf(elements, len + cs.length); |
824 if (len == 0 && cs.getClass() == Object[].class) |
788 System.arraycopy(cs, 0, newElements, len, cs.length); |
825 setArray(cs); |
789 setArray(newElements); |
826 else { |
|
827 Object[] newElements = Arrays.copyOf(elements, len + cs.length); |
|
828 System.arraycopy(cs, 0, newElements, len, cs.length); |
|
829 setArray(newElements); |
|
830 } |
790 return true; |
831 return true; |
791 } finally { |
832 } finally { |
792 lock.unlock(); |
833 lock.unlock(); |
793 } |
834 } |
794 } |
835 } |
838 } finally { |
879 } finally { |
839 lock.unlock(); |
880 lock.unlock(); |
840 } |
881 } |
841 } |
882 } |
842 |
883 |
|
884 public void forEach(Consumer<? super E> action) { |
|
885 if (action == null) throw new NullPointerException(); |
|
886 Object[] elements = getArray(); |
|
887 int len = elements.length; |
|
888 for (int i = 0; i < len; ++i) { |
|
889 @SuppressWarnings("unchecked") E e = (E) elements[i]; |
|
890 action.accept(e); |
|
891 } |
|
892 } |
|
893 |
|
894 public boolean removeIf(Predicate<? super E> filter) { |
|
895 if (filter == null) throw new NullPointerException(); |
|
896 final ReentrantLock lock = this.lock; |
|
897 lock.lock(); |
|
898 try { |
|
899 Object[] elements = getArray(); |
|
900 int len = elements.length; |
|
901 if (len != 0) { |
|
902 int newlen = 0; |
|
903 Object[] temp = new Object[len]; |
|
904 for (int i = 0; i < len; ++i) { |
|
905 @SuppressWarnings("unchecked") E e = (E) elements[i]; |
|
906 if (!filter.test(e)) |
|
907 temp[newlen++] = e; |
|
908 } |
|
909 if (newlen != len) { |
|
910 setArray(Arrays.copyOf(temp, newlen)); |
|
911 return true; |
|
912 } |
|
913 } |
|
914 return false; |
|
915 } finally { |
|
916 lock.unlock(); |
|
917 } |
|
918 } |
|
919 |
|
920 public void replaceAll(UnaryOperator<E> operator) { |
|
921 if (operator == null) throw new NullPointerException(); |
|
922 final ReentrantLock lock = this.lock; |
|
923 lock.lock(); |
|
924 try { |
|
925 Object[] elements = getArray(); |
|
926 int len = elements.length; |
|
927 Object[] newElements = Arrays.copyOf(elements, len); |
|
928 for (int i = 0; i < len; ++i) { |
|
929 @SuppressWarnings("unchecked") E e = (E) elements[i]; |
|
930 newElements[i] = operator.apply(e); |
|
931 } |
|
932 setArray(newElements); |
|
933 } finally { |
|
934 lock.unlock(); |
|
935 } |
|
936 } |
|
937 |
|
938 public void sort(Comparator<? super E> c) { |
|
939 final ReentrantLock lock = this.lock; |
|
940 lock.lock(); |
|
941 try { |
|
942 Object[] elements = getArray(); |
|
943 Object[] newElements = Arrays.copyOf(elements, elements.length); |
|
944 @SuppressWarnings("unchecked") E[] es = (E[])newElements; |
|
945 Arrays.sort(es, c); |
|
946 setArray(newElements); |
|
947 } finally { |
|
948 lock.unlock(); |
|
949 } |
|
950 } |
|
951 |
843 /** |
952 /** |
844 * Saves this list to a stream (that is, serializes it). |
953 * Saves this list to a stream (that is, serializes it). |
845 * |
954 * |
846 * @serialData The length of the array backing the list is emitted |
955 * @serialData The length of the array backing the list is emitted |
847 * (int), followed by all of its elements (each an Object) |
956 * (int), followed by all of its elements (each an Object) |
1033 return cursor-1; |
1147 return cursor-1; |
1034 } |
1148 } |
1035 |
1149 |
1036 /** |
1150 /** |
1037 * Not supported. Always throws UnsupportedOperationException. |
1151 * Not supported. Always throws UnsupportedOperationException. |
1038 * @throws UnsupportedOperationException always; <tt>remove</tt> |
1152 * @throws UnsupportedOperationException always; {@code remove} |
1039 * is not supported by this iterator. |
1153 * is not supported by this iterator. |
1040 */ |
1154 */ |
1041 public void remove() { |
1155 public void remove() { |
1042 throw new UnsupportedOperationException(); |
1156 throw new UnsupportedOperationException(); |
1043 } |
1157 } |
1044 |
1158 |
1045 /** |
1159 /** |
1046 * Not supported. Always throws UnsupportedOperationException. |
1160 * Not supported. Always throws UnsupportedOperationException. |
1047 * @throws UnsupportedOperationException always; <tt>set</tt> |
1161 * @throws UnsupportedOperationException always; {@code set} |
1048 * is not supported by this iterator. |
1162 * is not supported by this iterator. |
1049 */ |
1163 */ |
1050 public void set(E e) { |
1164 public void set(E e) { |
1051 throw new UnsupportedOperationException(); |
1165 throw new UnsupportedOperationException(); |
1052 } |
1166 } |
1053 |
1167 |
1054 /** |
1168 /** |
1055 * Not supported. Always throws UnsupportedOperationException. |
1169 * Not supported. Always throws UnsupportedOperationException. |
1056 * @throws UnsupportedOperationException always; <tt>add</tt> |
1170 * @throws UnsupportedOperationException always; {@code add} |
1057 * is not supported by this iterator. |
1171 * is not supported by this iterator. |
1058 */ |
1172 */ |
1059 public void add(E e) { |
1173 public void add(E e) { |
1060 throw new UnsupportedOperationException(); |
1174 throw new UnsupportedOperationException(); |
1061 } |
1175 } |
1062 |
1176 |
1063 @Override |
1177 @Override |
1064 @SuppressWarnings("unchecked") |
|
1065 public void forEachRemaining(Consumer<? super E> action) { |
1178 public void forEachRemaining(Consumer<? super E> action) { |
1066 Objects.requireNonNull(action); |
1179 Objects.requireNonNull(action); |
1067 final int size = snapshot.length; |
1180 Object[] elements = snapshot; |
1068 for (int i=cursor; i < size; i++) { |
1181 final int size = elements.length; |
1069 action.accept((E) snapshot[i]); |
1182 for (int i = cursor; i < size; i++) { |
|
1183 @SuppressWarnings("unchecked") E e = (E) elements[i]; |
|
1184 action.accept(e); |
1070 } |
1185 } |
1071 cursor = size; |
1186 cursor = size; |
1072 } |
1187 } |
1073 } |
1188 } |
1074 |
1189 |
1075 /** |
1190 /** |
1076 * Returns a view of the portion of this list between |
1191 * Returns a view of the portion of this list between |
1077 * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive. |
1192 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. |
1078 * The returned list is backed by this list, so changes in the |
1193 * The returned list is backed by this list, so changes in the |
1079 * returned list are reflected in this list. |
1194 * returned list are reflected in this list. |
1080 * |
1195 * |
1081 * <p>The semantics of the list returned by this method become |
1196 * <p>The semantics of the list returned by this method become |
1082 * undefined if the backing list (i.e., this list) is modified in |
1197 * undefined if the backing list (i.e., this list) is modified in |
1272 } finally { |
1387 } finally { |
1273 lock.unlock(); |
1388 lock.unlock(); |
1274 } |
1389 } |
1275 } |
1390 } |
1276 |
1391 |
1277 @Override |
|
1278 public void forEach(Consumer<? super E> action) { |
1392 public void forEach(Consumer<? super E> action) { |
1279 @SuppressWarnings("unchecked") |
1393 if (action == null) throw new NullPointerException(); |
1280 final E[] elements = (E[]) l.getArray(); |
1394 int lo = offset; |
1281 checkForComodification(); |
1395 int hi = offset + size; |
1282 l.forEach(action, elements, offset, offset + size); |
1396 Object[] a = expectedArray; |
1283 } |
1397 if (l.getArray() != a) |
1284 |
1398 throw new ConcurrentModificationException(); |
1285 @Override |
1399 if (lo < 0 || hi > a.length) |
|
1400 throw new IndexOutOfBoundsException(); |
|
1401 for (int i = lo; i < hi; ++i) { |
|
1402 @SuppressWarnings("unchecked") E e = (E) a[i]; |
|
1403 action.accept(e); |
|
1404 } |
|
1405 } |
|
1406 |
|
1407 public void replaceAll(UnaryOperator<E> operator) { |
|
1408 if (operator == null) throw new NullPointerException(); |
|
1409 final ReentrantLock lock = l.lock; |
|
1410 lock.lock(); |
|
1411 try { |
|
1412 int lo = offset; |
|
1413 int hi = offset + size; |
|
1414 Object[] elements = expectedArray; |
|
1415 if (l.getArray() != elements) |
|
1416 throw new ConcurrentModificationException(); |
|
1417 int len = elements.length; |
|
1418 if (lo < 0 || hi > len) |
|
1419 throw new IndexOutOfBoundsException(); |
|
1420 Object[] newElements = Arrays.copyOf(elements, len); |
|
1421 for (int i = lo; i < hi; ++i) { |
|
1422 @SuppressWarnings("unchecked") E e = (E) elements[i]; |
|
1423 newElements[i] = operator.apply(e); |
|
1424 } |
|
1425 l.setArray(expectedArray = newElements); |
|
1426 } finally { |
|
1427 lock.unlock(); |
|
1428 } |
|
1429 } |
|
1430 |
1286 public void sort(Comparator<? super E> c) { |
1431 public void sort(Comparator<? super E> c) { |
1287 final ReentrantLock lock = l.lock; |
1432 final ReentrantLock lock = l.lock; |
1288 lock.lock(); |
1433 lock.lock(); |
1289 try { |
1434 try { |
1290 checkForComodification(); |
1435 int lo = offset; |
1291 l.sort(c, offset, offset + size); |
1436 int hi = offset + size; |
1292 expectedArray = l.getArray(); |
1437 Object[] elements = expectedArray; |
|
1438 if (l.getArray() != elements) |
|
1439 throw new ConcurrentModificationException(); |
|
1440 int len = elements.length; |
|
1441 if (lo < 0 || hi > len) |
|
1442 throw new IndexOutOfBoundsException(); |
|
1443 Object[] newElements = Arrays.copyOf(elements, len); |
|
1444 @SuppressWarnings("unchecked") E[] es = (E[])newElements; |
|
1445 Arrays.sort(es, lo, hi, c); |
|
1446 l.setArray(expectedArray = newElements); |
1293 } finally { |
1447 } finally { |
1294 lock.unlock(); |
1448 lock.unlock(); |
1295 } |
1449 } |
1296 } |
1450 } |
1297 |
1451 |
1298 @Override |
1452 public boolean removeAll(Collection<?> c) { |
1299 public boolean removeIf(Predicate<? super E> filter) { |
1453 if (c == null) throw new NullPointerException(); |
1300 Objects.requireNonNull(filter); |
1454 boolean removed = false; |
1301 final ReentrantLock lock = l.lock; |
1455 final ReentrantLock lock = l.lock; |
1302 lock.lock(); |
1456 lock.lock(); |
1303 try { |
1457 try { |
1304 checkForComodification(); |
1458 int n = size; |
1305 final int removeCount = |
1459 if (n > 0) { |
1306 l.removeIf(filter, offset, offset + size); |
1460 int lo = offset; |
1307 expectedArray = l.getArray(); |
1461 int hi = offset + n; |
1308 size -= removeCount; |
1462 Object[] elements = expectedArray; |
1309 return removeCount > 0; |
1463 if (l.getArray() != elements) |
|
1464 throw new ConcurrentModificationException(); |
|
1465 int len = elements.length; |
|
1466 if (lo < 0 || hi > len) |
|
1467 throw new IndexOutOfBoundsException(); |
|
1468 int newSize = 0; |
|
1469 Object[] temp = new Object[n]; |
|
1470 for (int i = lo; i < hi; ++i) { |
|
1471 Object element = elements[i]; |
|
1472 if (!c.contains(element)) |
|
1473 temp[newSize++] = element; |
|
1474 } |
|
1475 if (newSize != n) { |
|
1476 Object[] newElements = new Object[len - n + newSize]; |
|
1477 System.arraycopy(elements, 0, newElements, 0, lo); |
|
1478 System.arraycopy(temp, 0, newElements, lo, newSize); |
|
1479 System.arraycopy(elements, hi, newElements, |
|
1480 lo + newSize, len - hi); |
|
1481 size = newSize; |
|
1482 removed = true; |
|
1483 l.setArray(expectedArray = newElements); |
|
1484 } |
|
1485 } |
1310 } finally { |
1486 } finally { |
1311 lock.unlock(); |
1487 lock.unlock(); |
1312 } |
1488 } |
1313 } |
1489 return removed; |
1314 |
1490 } |
1315 @Override |
1491 |
1316 public void replaceAll(UnaryOperator<E> operator) { |
1492 public boolean retainAll(Collection<?> c) { |
|
1493 if (c == null) throw new NullPointerException(); |
|
1494 boolean removed = false; |
1317 final ReentrantLock lock = l.lock; |
1495 final ReentrantLock lock = l.lock; |
1318 lock.lock(); |
1496 lock.lock(); |
1319 try { |
1497 try { |
1320 checkForComodification(); |
1498 int n = size; |
1321 l.replaceAll(operator, offset, offset + size); |
1499 if (n > 0) { |
1322 expectedArray = l.getArray(); |
1500 int lo = offset; |
|
1501 int hi = offset + n; |
|
1502 Object[] elements = expectedArray; |
|
1503 if (l.getArray() != elements) |
|
1504 throw new ConcurrentModificationException(); |
|
1505 int len = elements.length; |
|
1506 if (lo < 0 || hi > len) |
|
1507 throw new IndexOutOfBoundsException(); |
|
1508 int newSize = 0; |
|
1509 Object[] temp = new Object[n]; |
|
1510 for (int i = lo; i < hi; ++i) { |
|
1511 Object element = elements[i]; |
|
1512 if (c.contains(element)) |
|
1513 temp[newSize++] = element; |
|
1514 } |
|
1515 if (newSize != n) { |
|
1516 Object[] newElements = new Object[len - n + newSize]; |
|
1517 System.arraycopy(elements, 0, newElements, 0, lo); |
|
1518 System.arraycopy(temp, 0, newElements, lo, newSize); |
|
1519 System.arraycopy(elements, hi, newElements, |
|
1520 lo + newSize, len - hi); |
|
1521 size = newSize; |
|
1522 removed = true; |
|
1523 l.setArray(expectedArray = newElements); |
|
1524 } |
|
1525 } |
1323 } finally { |
1526 } finally { |
1324 lock.unlock(); |
1527 lock.unlock(); |
1325 } |
1528 } |
|
1529 return removed; |
|
1530 } |
|
1531 |
|
1532 public boolean removeIf(Predicate<? super E> filter) { |
|
1533 if (filter == null) throw new NullPointerException(); |
|
1534 boolean removed = false; |
|
1535 final ReentrantLock lock = l.lock; |
|
1536 lock.lock(); |
|
1537 try { |
|
1538 int n = size; |
|
1539 if (n > 0) { |
|
1540 int lo = offset; |
|
1541 int hi = offset + n; |
|
1542 Object[] elements = expectedArray; |
|
1543 if (l.getArray() != elements) |
|
1544 throw new ConcurrentModificationException(); |
|
1545 int len = elements.length; |
|
1546 if (lo < 0 || hi > len) |
|
1547 throw new IndexOutOfBoundsException(); |
|
1548 int newSize = 0; |
|
1549 Object[] temp = new Object[n]; |
|
1550 for (int i = lo; i < hi; ++i) { |
|
1551 @SuppressWarnings("unchecked") E e = (E) elements[i]; |
|
1552 if (!filter.test(e)) |
|
1553 temp[newSize++] = e; |
|
1554 } |
|
1555 if (newSize != n) { |
|
1556 Object[] newElements = new Object[len - n + newSize]; |
|
1557 System.arraycopy(elements, 0, newElements, 0, lo); |
|
1558 System.arraycopy(temp, 0, newElements, lo, newSize); |
|
1559 System.arraycopy(elements, hi, newElements, |
|
1560 lo + newSize, len - hi); |
|
1561 size = newSize; |
|
1562 removed = true; |
|
1563 l.setArray(expectedArray = newElements); |
|
1564 } |
|
1565 } |
|
1566 } finally { |
|
1567 lock.unlock(); |
|
1568 } |
|
1569 return removed; |
|
1570 } |
|
1571 |
|
1572 public Spliterator<E> spliterator() { |
|
1573 int lo = offset; |
|
1574 int hi = offset + size; |
|
1575 Object[] a = expectedArray; |
|
1576 if (l.getArray() != a) |
|
1577 throw new ConcurrentModificationException(); |
|
1578 if (lo < 0 || hi > a.length) |
|
1579 throw new IndexOutOfBoundsException(); |
|
1580 return Spliterators.spliterator |
|
1581 (a, lo, hi, Spliterator.IMMUTABLE | Spliterator.ORDERED); |
1326 } |
1582 } |
1327 } |
1583 } |
1328 |
1584 |
1329 private static class COWSubListIterator<E> implements ListIterator<E> { |
1585 private static class COWSubListIterator<E> implements ListIterator<E> { |
1330 private final ListIterator<E> it; |
1586 private final ListIterator<E> it; |
1403 (k.getDeclaredField("lock")); |
1660 (k.getDeclaredField("lock")); |
1404 } catch (Exception e) { |
1661 } catch (Exception e) { |
1405 throw new Error(e); |
1662 throw new Error(e); |
1406 } |
1663 } |
1407 } |
1664 } |
1408 |
|
1409 @Override |
|
1410 @SuppressWarnings("unchecked") |
|
1411 public void forEach(Consumer<? super E> action) { |
|
1412 forEach(action, (E[]) getArray(), 0, size()); |
|
1413 } |
|
1414 |
|
1415 private void forEach(Consumer<? super E> action, |
|
1416 final E[] elements, |
|
1417 final int from, final int to) { |
|
1418 Objects.requireNonNull(action); |
|
1419 for (int i = from; i < to; i++) { |
|
1420 action.accept(elements[i]); |
|
1421 } |
|
1422 } |
|
1423 |
|
1424 @Override |
|
1425 public void sort(Comparator<? super E> c) { |
|
1426 final ReentrantLock lock = this.lock; |
|
1427 lock.lock(); |
|
1428 try { |
|
1429 sort(c, 0, size()); |
|
1430 } finally { |
|
1431 lock.unlock(); |
|
1432 } |
|
1433 } |
|
1434 |
|
1435 // must be called with this.lock held |
|
1436 @SuppressWarnings("unchecked") |
|
1437 private void sort(Comparator<? super E> c, final int from, final int to) { |
|
1438 final E[] elements = (E[]) getArray(); |
|
1439 final E[] newElements = Arrays.copyOf(elements, elements.length); |
|
1440 // only elements [from, to) are sorted |
|
1441 Arrays.sort(newElements, from, to, c); |
|
1442 setArray(newElements); |
|
1443 } |
|
1444 |
|
1445 @Override |
|
1446 public boolean removeIf(Predicate<? super E> filter) { |
|
1447 Objects.requireNonNull(filter); |
|
1448 final ReentrantLock lock = this.lock; |
|
1449 lock.lock(); |
|
1450 try { |
|
1451 return removeIf(filter, 0, size()) > 0; |
|
1452 } finally { |
|
1453 lock.unlock(); |
|
1454 } |
|
1455 } |
|
1456 |
|
1457 // must be called with this.lock held |
|
1458 private int removeIf(Predicate<? super E> filter, final int from, final int to) { |
|
1459 Objects.requireNonNull(filter); |
|
1460 final ReentrantLock lock = this.lock; |
|
1461 lock.lock(); |
|
1462 try { |
|
1463 @SuppressWarnings("unchecked") |
|
1464 final E[] elements = (E[]) getArray(); |
|
1465 |
|
1466 // figure out which elements are to be removed |
|
1467 // any exception thrown from the filter predicate at this stage |
|
1468 // will leave the collection unmodified |
|
1469 int removeCount = 0; |
|
1470 final int range = to - from; |
|
1471 final BitSet removeSet = new BitSet(range); |
|
1472 for (int i = 0; i < range; i++) { |
|
1473 final E element = elements[from + i]; |
|
1474 if (filter.test(element)) { |
|
1475 // removeSet is zero-based to keep its size small |
|
1476 removeSet.set(i); |
|
1477 removeCount++; |
|
1478 } |
|
1479 } |
|
1480 |
|
1481 // copy surviving elements into a new array |
|
1482 if (removeCount > 0) { |
|
1483 final int newSize = elements.length - removeCount; |
|
1484 final int newRange = newSize - from; |
|
1485 @SuppressWarnings("unchecked") |
|
1486 final E[] newElements = (E[]) new Object[newSize]; |
|
1487 // copy elements before [from, to) unmodified |
|
1488 for (int i = 0; i < from; i++) { |
|
1489 newElements[i] = elements[i]; |
|
1490 } |
|
1491 // elements [from, to) are subject to removal |
|
1492 int j = 0; |
|
1493 for (int i = 0; (i < range) && (j < newRange); i++) { |
|
1494 i = removeSet.nextClearBit(i); |
|
1495 if (i >= range) { |
|
1496 break; |
|
1497 } |
|
1498 newElements[from + (j++)] = elements[from + i]; |
|
1499 } |
|
1500 // copy any remaining elements beyond [from, to) |
|
1501 j += from; |
|
1502 for (int i = to; (i < elements.length) && (j < newSize); i++) { |
|
1503 newElements[j++] = elements[i]; |
|
1504 } |
|
1505 setArray(newElements); |
|
1506 } |
|
1507 |
|
1508 return removeCount; |
|
1509 } finally { |
|
1510 lock.unlock(); |
|
1511 } |
|
1512 } |
|
1513 |
|
1514 @Override |
|
1515 public void replaceAll(UnaryOperator<E> operator) { |
|
1516 Objects.requireNonNull(operator); |
|
1517 final ReentrantLock lock = this.lock; |
|
1518 lock.lock(); |
|
1519 try { |
|
1520 replaceAll(operator, 0, size()); |
|
1521 } finally { |
|
1522 lock.unlock(); |
|
1523 } |
|
1524 } |
|
1525 |
|
1526 // must be called with this.lock held |
|
1527 @SuppressWarnings("unchecked") |
|
1528 private void replaceAll(UnaryOperator<E> operator, final int from, final int to) { |
|
1529 final E[] elements = (E[]) getArray(); |
|
1530 final E[] newElements = (E[]) new Object[elements.length]; |
|
1531 for (int i = 0; i < from; i++) { |
|
1532 newElements[i] = elements[i]; |
|
1533 } |
|
1534 // the operator is only applied to elements [from, to) |
|
1535 for (int i = from; i < to; i++) { |
|
1536 newElements[i] = operator.apply(elements[i]); |
|
1537 } |
|
1538 for (int i = to; i < elements.length; i++) { |
|
1539 newElements[i] = elements[i]; |
|
1540 } |
|
1541 setArray(newElements); |
|
1542 } |
|
1543 } |
1665 } |