1 /*
   2  * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  * Written by Doug Lea with assistance from members of JCP JSR-166
  28  * Expert Group.  Adapted and released, under explicit permission,
  29  * from JDK ArrayList.java which carries the following copyright:
  30  *
  31  * Copyright 1997 by Sun Microsystems, Inc.,
  32  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  33  * All rights reserved.
  34  */
  35 
  36 package java.util.concurrent;
  37 import java.util.*;
  38 import java.util.concurrent.locks.ReentrantLock;
  39 import java.util.function.Consumer;
  40 import java.util.function.Predicate;
  41 import java.util.function.UnaryOperator;
  42 
  43 /**
  44  * 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
  46  * making a fresh copy of the underlying array.
  47  *
  48  * <p> This is ordinarily too costly, but may be <em>more</em> efficient
  49  * than alternatives when traversal operations vastly outnumber
  50  * mutations, and is useful when you cannot or don't want to
  51  * synchronize traversals, yet need to preclude interference among
  52  * concurrent threads.  The "snapshot" style iterator method uses a
  53  * 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
  55  * iterator, so interference is impossible and the iterator is
  56  * guaranteed not to throw <tt>ConcurrentModificationException</tt>.
  57  * The iterator will not reflect additions, removals, or changes to
  58  * the list since the iterator was created.  Element-changing
  59  * operations on iterators themselves (<tt>remove</tt>, <tt>set</tt>, and
  60  * <tt>add</tt>) are not supported. These methods throw
  61  * <tt>UnsupportedOperationException</tt>.
  62  *
  63  * <p>All elements are permitted, including <tt>null</tt>.
  64  *
  65  * <p>Memory consistency effects: As with other concurrent
  66  * collections, actions in a thread prior to placing an object into a
  67  * {@code CopyOnWriteArrayList}
  68  * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
  69  * actions subsequent to the access or removal of that element from
  70  * the {@code CopyOnWriteArrayList} in another thread.
  71  *
  72  * <p>This class is a member of the
  73  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  74  * Java Collections Framework</a>.
  75  *
  76  * @since 1.5
  77  * @author Doug Lea
  78  * @param <E> the type of elements held in this collection
  79  */
  80 public class CopyOnWriteArrayList<E>
  81     implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
  82     private static final long serialVersionUID = 8673264195747942595L;
  83 
  84     /** The lock protecting all mutators */
  85     transient final ReentrantLock lock = new ReentrantLock();
  86 
  87     /** The array, accessed only via getArray/setArray. */
  88     private volatile transient Object[] array;
  89 
  90     /**
  91      * Gets the array.  Non-private so as to also be accessible
  92      * from CopyOnWriteArraySet class.
  93      */
  94     final Object[] getArray() {
  95         return array;
  96     }
  97 
  98     /**
  99      * Sets the array.
 100      */
 101     final void setArray(Object[] a) {
 102         array = a;
 103     }
 104 
 105     /**
 106      * Creates an empty list.
 107      */
 108     public CopyOnWriteArrayList() {
 109         setArray(new Object[0]);
 110     }
 111 
 112     /**
 113      * Creates a list containing the elements of the specified
 114      * collection, in the order they are returned by the collection's
 115      * iterator.
 116      *
 117      * @param c the collection of initially held elements
 118      * @throws NullPointerException if the specified collection is null
 119      */
 120     public CopyOnWriteArrayList(Collection<? extends E> c) {
 121         Object[] elements = c.toArray();
 122         // c.toArray might (incorrectly) not return Object[] (see 6260652)
 123         if (elements.getClass() != Object[].class)
 124             elements = Arrays.copyOf(elements, elements.length, Object[].class);
 125         setArray(elements);
 126     }
 127 
 128     /**
 129      * Creates a list holding a copy of the given array.
 130      *
 131      * @param toCopyIn the array (a copy of this array is used as the
 132      *        internal array)
 133      * @throws NullPointerException if the specified array is null
 134      */
 135     public CopyOnWriteArrayList(E[] toCopyIn) {
 136         setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
 137     }
 138 
 139     /**
 140      * Returns the number of elements in this list.
 141      *
 142      * @return the number of elements in this list
 143      */
 144     public int size() {
 145         return getArray().length;
 146     }
 147 
 148     /**
 149      * Returns <tt>true</tt> if this list contains no elements.
 150      *
 151      * @return <tt>true</tt> if this list contains no elements
 152      */
 153     public boolean isEmpty() {
 154         return size() == 0;
 155     }
 156 
 157     /**
 158      * Tests for equality, coping with nulls.
 159      */
 160     private static boolean eq(Object o1, Object o2) {
 161         return (o1 == null ? o2 == null : o1.equals(o2));
 162     }
 163 
 164     /**
 165      * static version of indexOf, to allow repeated calls without
 166      * needing to re-acquire array each time.
 167      * @param o element to search for
 168      * @param elements the array
 169      * @param index first index to search
 170      * @param fence one past last index to search
 171      * @return index of element, or -1 if absent
 172      */
 173     private static int indexOf(Object o, Object[] elements,
 174                                int index, int fence) {
 175         if (o == null) {
 176             for (int i = index; i < fence; i++)
 177                 if (elements[i] == null)
 178                     return i;
 179         } else {
 180             for (int i = index; i < fence; i++)
 181                 if (o.equals(elements[i]))
 182                     return i;
 183         }
 184         return -1;
 185     }
 186 
 187     /**
 188      * static version of lastIndexOf.
 189      * @param o element to search for
 190      * @param elements the array
 191      * @param index first index to search
 192      * @return index of element, or -1 if absent
 193      */
 194     private static int lastIndexOf(Object o, Object[] elements, int index) {
 195         if (o == null) {
 196             for (int i = index; i >= 0; i--)
 197                 if (elements[i] == null)
 198                     return i;
 199         } else {
 200             for (int i = index; i >= 0; i--)
 201                 if (o.equals(elements[i]))
 202                     return i;
 203         }
 204         return -1;
 205     }
 206 
 207     /**
 208      * Returns <tt>true</tt> if this list contains the specified element.
 209      * More formally, returns <tt>true</tt> if and only if this list contains
 210      * at least one element <tt>e</tt> such that
 211      * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
 212      *
 213      * @param o element whose presence in this list is to be tested
 214      * @return <tt>true</tt> if this list contains the specified element
 215      */
 216     public boolean contains(Object o) {
 217         Object[] elements = getArray();
 218         return indexOf(o, elements, 0, elements.length) >= 0;
 219     }
 220 
 221     /**
 222      * {@inheritDoc}
 223      */
 224     public int indexOf(Object o) {
 225         Object[] elements = getArray();
 226         return indexOf(o, elements, 0, elements.length);
 227     }
 228 
 229     /**
 230      * 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
 232      * the element is not found.
 233      * More formally, returns the lowest index <tt>i</tt> such that
 234      * <tt>(i&nbsp;&gt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(e==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;e.equals(get(i))))</tt>,
 235      * or -1 if there is no such index.
 236      *
 237      * @param e element to search for
 238      * @param index index to start searching from
 239      * @return the index of the first occurrence of the element in
 240      *         this list at position <tt>index</tt> or later in the list;
 241      *         <tt>-1</tt> if the element is not found.
 242      * @throws IndexOutOfBoundsException if the specified index is negative
 243      */
 244     public int indexOf(E e, int index) {
 245         Object[] elements = getArray();
 246         return indexOf(e, elements, index, elements.length);
 247     }
 248 
 249     /**
 250      * {@inheritDoc}
 251      */
 252     public int lastIndexOf(Object o) {
 253         Object[] elements = getArray();
 254         return lastIndexOf(o, elements, elements.length - 1);
 255     }
 256 
 257     /**
 258      * 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
 260      * the element is not found.
 261      * More formally, returns the highest index <tt>i</tt> such that
 262      * <tt>(i&nbsp;&lt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(e==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;e.equals(get(i))))</tt>,
 263      * or -1 if there is no such index.
 264      *
 265      * @param e element to search for
 266      * @param index index to start searching backwards from
 267      * @return the index of the last occurrence of the element at position
 268      *         less than or equal to <tt>index</tt> in this list;
 269      *         -1 if the element is not found.
 270      * @throws IndexOutOfBoundsException if the specified index is greater
 271      *         than or equal to the current size of this list
 272      */
 273     public int lastIndexOf(E e, int index) {
 274         Object[] elements = getArray();
 275         return lastIndexOf(e, elements, index);
 276     }
 277 
 278     /**
 279      * Returns a shallow copy of this list.  (The elements themselves
 280      * are not copied.)
 281      *
 282      * @return a clone of this list
 283      */
 284     public Object clone() {
 285         try {
 286             @SuppressWarnings("unchecked")
 287             CopyOnWriteArrayList<E> clone =
 288                 (CopyOnWriteArrayList<E>) super.clone();
 289             clone.resetLock();
 290             return clone;
 291         } catch (CloneNotSupportedException e) {
 292             // this shouldn't happen, since we are Cloneable
 293             throw new InternalError();
 294         }
 295     }
 296 
 297     /**
 298      * Returns an array containing all of the elements in this list
 299      * in proper sequence (from first to last element).
 300      *
 301      * <p>The returned array will be "safe" in that no references to it are
 302      * maintained by this list.  (In other words, this method must allocate
 303      * a new array).  The caller is thus free to modify the returned array.
 304      *
 305      * <p>This method acts as bridge between array-based and collection-based
 306      * APIs.
 307      *
 308      * @return an array containing all the elements in this list
 309      */
 310     public Object[] toArray() {
 311         Object[] elements = getArray();
 312         return Arrays.copyOf(elements, elements.length);
 313     }
 314 
 315     /**
 316      * Returns an array containing all of the elements in this list in
 317      * proper sequence (from first to last element); the runtime type of
 318      * the returned array is that of the specified array.  If the list fits
 319      * in the specified array, it is returned therein.  Otherwise, a new
 320      * array is allocated with the runtime type of the specified array and
 321      * the size of this list.
 322      *
 323      * <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
 325      * 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
 327      * list <i>only</i> if the caller knows that this list does not contain
 328      * any null elements.)
 329      *
 330      * <p>Like the {@link #toArray()} method, this method acts as bridge between
 331      * array-based and collection-based APIs.  Further, this method allows
 332      * precise control over the runtime type of the output array, and may,
 333      * under certain circumstances, be used to save allocation costs.
 334      *
 335      * <p>Suppose <tt>x</tt> is a list known to contain only strings.
 336      * The following code can be used to dump the list into a newly
 337      * allocated array of <tt>String</tt>:
 338      *
 339      *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
 340      *
 341      * Note that <tt>toArray(new Object[0])</tt> is identical in function to
 342      * <tt>toArray()</tt>.
 343      *
 344      * @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
 346      *          same runtime type is allocated for this purpose.
 347      * @return an array containing all the elements in this list
 348      * @throws ArrayStoreException if the runtime type of the specified array
 349      *         is not a supertype of the runtime type of every element in
 350      *         this list
 351      * @throws NullPointerException if the specified array is null
 352      */
 353     @SuppressWarnings("unchecked")
 354     public <T> T[] toArray(T a[]) {
 355         Object[] elements = getArray();
 356         int len = elements.length;
 357         if (a.length < len)
 358             return (T[]) Arrays.copyOf(elements, len, a.getClass());
 359         else {
 360             System.arraycopy(elements, 0, a, 0, len);
 361             if (a.length > len)
 362                 a[len] = null;
 363             return a;
 364         }
 365     }
 366 
 367     // Positional Access Operations
 368 
 369     @SuppressWarnings("unchecked")
 370     private E get(Object[] a, int index) {
 371         return (E) a[index];
 372     }
 373 
 374     /**
 375      * {@inheritDoc}
 376      *
 377      * @throws IndexOutOfBoundsException {@inheritDoc}
 378      */
 379     public E get(int index) {
 380         return get(getArray(), index);
 381     }
 382 
 383     /**
 384      * Replaces the element at the specified position in this list with the
 385      * specified element.
 386      *
 387      * @throws IndexOutOfBoundsException {@inheritDoc}
 388      */
 389     public E set(int index, E element) {
 390         final ReentrantLock lock = this.lock;
 391         lock.lock();
 392         try {
 393             Object[] elements = getArray();
 394             E oldValue = get(elements, index);
 395 
 396             if (oldValue != element) {
 397                 int len = elements.length;
 398                 Object[] newElements = Arrays.copyOf(elements, len);
 399                 newElements[index] = element;
 400                 setArray(newElements);
 401             } else {
 402                 // Not quite a no-op; ensures volatile write semantics
 403                 setArray(elements);
 404             }
 405             return oldValue;
 406         } finally {
 407             lock.unlock();
 408         }
 409     }
 410 
 411     /**
 412      * Appends the specified element to the end of this list.
 413      *
 414      * @param e element to be appended to this list
 415      * @return <tt>true</tt> (as specified by {@link Collection#add})
 416      */
 417     public boolean add(E e) {
 418         final ReentrantLock lock = this.lock;
 419         lock.lock();
 420         try {
 421             Object[] elements = getArray();
 422             int len = elements.length;
 423             Object[] newElements = Arrays.copyOf(elements, len + 1);
 424             newElements[len] = e;
 425             setArray(newElements);
 426             return true;
 427         } finally {
 428             lock.unlock();
 429         }
 430     }
 431 
 432     /**
 433      * Inserts the specified element at the specified position in this
 434      * list. Shifts the element currently at that position (if any) and
 435      * any subsequent elements to the right (adds one to their indices).
 436      *
 437      * @throws IndexOutOfBoundsException {@inheritDoc}
 438      */
 439     public void add(int index, E element) {
 440         final ReentrantLock lock = this.lock;
 441         lock.lock();
 442         try {
 443             Object[] elements = getArray();
 444             int len = elements.length;
 445             if (index > len || index < 0)
 446                 throw new IndexOutOfBoundsException("Index: "+index+
 447                                                     ", Size: "+len);
 448             Object[] newElements;
 449             int numMoved = len - index;
 450             if (numMoved == 0)
 451                 newElements = Arrays.copyOf(elements, len + 1);
 452             else {
 453                 newElements = new Object[len + 1];
 454                 System.arraycopy(elements, 0, newElements, 0, index);
 455                 System.arraycopy(elements, index, newElements, index + 1,
 456                                  numMoved);
 457             }
 458             newElements[index] = element;
 459             setArray(newElements);
 460         } finally {
 461             lock.unlock();
 462         }
 463     }
 464 
 465     /**
 466      * Removes the element at the specified position in this list.
 467      * Shifts any subsequent elements to the left (subtracts one from their
 468      * indices).  Returns the element that was removed from the list.
 469      *
 470      * @throws IndexOutOfBoundsException {@inheritDoc}
 471      */
 472     public E remove(int index) {
 473         final ReentrantLock lock = this.lock;
 474         lock.lock();
 475         try {
 476             Object[] elements = getArray();
 477             int len = elements.length;
 478             E oldValue = get(elements, index);
 479             int numMoved = len - index - 1;
 480             if (numMoved == 0)
 481                 setArray(Arrays.copyOf(elements, len - 1));
 482             else {
 483                 Object[] newElements = new Object[len - 1];
 484                 System.arraycopy(elements, 0, newElements, 0, index);
 485                 System.arraycopy(elements, index + 1, newElements, index,
 486                                  numMoved);
 487                 setArray(newElements);
 488             }
 489             return oldValue;
 490         } finally {
 491             lock.unlock();
 492         }
 493     }
 494 
 495     /**
 496      * 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
 498      * unchanged.  More formally, removes the element with the lowest index
 499      * <tt>i</tt> such that
 500      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
 501      * (if such an element exists).  Returns <tt>true</tt> if this list
 502      * contained the specified element (or equivalently, if this list
 503      * changed as a result of the call).
 504      *
 505      * @param o element to be removed from this list, if present
 506      * @return <tt>true</tt> if this list contained the specified element
 507      */
 508     public boolean remove(Object o) {
 509         final ReentrantLock lock = this.lock;
 510         lock.lock();
 511         try {
 512             Object[] elements = getArray();
 513             int len = elements.length;
 514             if (len != 0) {
 515                 // Copy while searching for element to remove
 516                 // This wins in the normal case of element being present
 517                 int newlen = len - 1;
 518                 Object[] newElements = new Object[newlen];
 519 
 520                 for (int i = 0; i < newlen; ++i) {
 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                 }
 530 
 531                 // special handling for last cell
 532                 if (eq(o, elements[newlen])) {
 533                     setArray(newElements);
 534                     return true;
 535                 }
 536             }
 537             return false;
 538         } finally {
 539             lock.unlock();
 540         }
 541     }
 542 
 543     /**
 544      * Removes from this list all of the elements whose index is between
 545      * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
 546      * Shifts any succeeding elements to the left (reduces their index).
 547      * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
 548      * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
 549      *
 550      * @param fromIndex index of first element to be removed
 551      * @param toIndex index after last element to be removed
 552      * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range
 553      *         ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
 554      */
 555     void removeRange(int fromIndex, int toIndex) {
 556         final ReentrantLock lock = this.lock;
 557         lock.lock();
 558         try {
 559             Object[] elements = getArray();
 560             int len = elements.length;
 561 
 562             if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
 563                 throw new IndexOutOfBoundsException();
 564             int newlen = len - (toIndex - fromIndex);
 565             int numMoved = len - toIndex;
 566             if (numMoved == 0)
 567                 setArray(Arrays.copyOf(elements, newlen));
 568             else {
 569                 Object[] newElements = new Object[newlen];
 570                 System.arraycopy(elements, 0, newElements, 0, fromIndex);
 571                 System.arraycopy(elements, toIndex, newElements,
 572                                  fromIndex, numMoved);
 573                 setArray(newElements);
 574             }
 575         } finally {
 576             lock.unlock();
 577         }
 578     }
 579 
 580     /**
 581      * Appends the element, if not present.
 582      *
 583      * @param e element to be added to this list, if absent
 584      * @return <tt>true</tt> if the element was added
 585      */
 586     public boolean addIfAbsent(E e) {
 587         final ReentrantLock lock = this.lock;
 588         lock.lock();
 589         try {
 590             // Copy while checking if already present.
 591             // This wins in the most common case where it is not present
 592             Object[] elements = getArray();
 593             int len = elements.length;
 594             Object[] newElements = new Object[len + 1];
 595             for (int i = 0; i < len; ++i) {
 596                 if (eq(e, elements[i]))
 597                     return false; // exit, throwing away copy
 598                 else
 599                     newElements[i] = elements[i];
 600             }
 601             newElements[len] = e;
 602             setArray(newElements);
 603             return true;
 604         } finally {
 605             lock.unlock();
 606         }
 607     }
 608 
 609     /**
 610      * Returns <tt>true</tt> if this list contains all of the elements of the
 611      * specified collection.
 612      *
 613      * @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
 615      *         specified collection
 616      * @throws NullPointerException if the specified collection is null
 617      * @see #contains(Object)
 618      */
 619     public boolean containsAll(Collection<?> c) {
 620         Object[] elements = getArray();
 621         int len = elements.length;
 622         for (Object e : c) {
 623             if (indexOf(e, elements, 0, len) < 0)
 624                 return false;
 625         }
 626         return true;
 627     }
 628 
 629     /**
 630      * Removes from this list all of its elements that are contained in
 631      * the specified collection. This is a particularly expensive operation
 632      * in this class because of the need for an internal temporary array.
 633      *
 634      * @param c collection containing elements to be removed from this list
 635      * @return <tt>true</tt> if this list changed as a result of the call
 636      * @throws ClassCastException if the class of an element of this list
 637      *         is incompatible with the specified collection
 638      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
 639      * @throws NullPointerException if this list contains a null element and the
 640      *         specified collection does not permit null elements
 641      *         (<a href="../Collection.html#optional-restrictions">optional</a>),
 642      *         or if the specified collection is null
 643      * @see #remove(Object)
 644      */
 645     public boolean removeAll(Collection<?> c) {
 646         if (c == null) throw new NullPointerException();
 647         final ReentrantLock lock = this.lock;
 648         lock.lock();
 649         try {
 650             Object[] elements = getArray();
 651             int len = elements.length;
 652             if (len != 0) {
 653                 // temp array holds those elements we know we want to keep
 654                 int newlen = 0;
 655                 Object[] temp = new Object[len];
 656                 for (int i = 0; i < len; ++i) {
 657                     Object element = elements[i];
 658                     if (!c.contains(element))
 659                         temp[newlen++] = element;
 660                 }
 661                 if (newlen != len) {
 662                     setArray(Arrays.copyOf(temp, newlen));
 663                     return true;
 664                 }
 665             }
 666             return false;
 667         } finally {
 668             lock.unlock();
 669         }
 670     }
 671 
 672     /**
 673      * Retains only the elements in this list that are contained in the
 674      * specified collection.  In other words, removes from this list all of
 675      * its elements that are not contained in the specified collection.
 676      *
 677      * @param c collection containing elements to be retained in this list
 678      * @return <tt>true</tt> if this list changed as a result of the call
 679      * @throws ClassCastException if the class of an element of this list
 680      *         is incompatible with the specified collection
 681      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
 682      * @throws NullPointerException if this list contains a null element and the
 683      *         specified collection does not permit null elements
 684      *         (<a href="../Collection.html#optional-restrictions">optional</a>),
 685      *         or if the specified collection is null
 686      * @see #remove(Object)
 687      */
 688     public boolean retainAll(Collection<?> c) {
 689         if (c == null) throw new NullPointerException();
 690         final ReentrantLock lock = this.lock;
 691         lock.lock();
 692         try {
 693             Object[] elements = getArray();
 694             int len = elements.length;
 695             if (len != 0) {
 696                 // temp array holds those elements we know we want to keep
 697                 int newlen = 0;
 698                 Object[] temp = new Object[len];
 699                 for (int i = 0; i < len; ++i) {
 700                     Object element = elements[i];
 701                     if (c.contains(element))
 702                         temp[newlen++] = element;
 703                 }
 704                 if (newlen != len) {
 705                     setArray(Arrays.copyOf(temp, newlen));
 706                     return true;
 707                 }
 708             }
 709             return false;
 710         } finally {
 711             lock.unlock();
 712         }
 713     }
 714 
 715     /**
 716      * Appends all of the elements in the specified collection that
 717      * are not already contained in this list, to the end of
 718      * this list, in the order that they are returned by the
 719      * specified collection's iterator.
 720      *
 721      * @param c collection containing elements to be added to this list
 722      * @return the number of elements added
 723      * @throws NullPointerException if the specified collection is null
 724      * @see #addIfAbsent(Object)
 725      */
 726     public int addAllAbsent(Collection<? extends E> c) {
 727         Object[] cs = c.toArray();
 728         if (cs.length == 0)
 729             return 0;
 730         Object[] uniq = new Object[cs.length];
 731         final ReentrantLock lock = this.lock;
 732         lock.lock();
 733         try {
 734             Object[] elements = getArray();
 735             int len = elements.length;
 736             int added = 0;
 737             for (int i = 0; i < cs.length; ++i) { // scan for duplicates
 738                 Object e = cs[i];
 739                 if (indexOf(e, elements, 0, len) < 0 &&
 740                     indexOf(e, uniq, 0, added) < 0)
 741                     uniq[added++] = e;
 742             }
 743             if (added > 0) {
 744                 Object[] newElements = Arrays.copyOf(elements, len + added);
 745                 System.arraycopy(uniq, 0, newElements, len, added);
 746                 setArray(newElements);
 747             }
 748             return added;
 749         } finally {
 750             lock.unlock();
 751         }
 752     }
 753 
 754     /**
 755      * Removes all of the elements from this list.
 756      * The list will be empty after this call returns.
 757      */
 758     public void clear() {
 759         final ReentrantLock lock = this.lock;
 760         lock.lock();
 761         try {
 762             setArray(new Object[0]);
 763         } finally {
 764             lock.unlock();
 765         }
 766     }
 767 
 768     /**
 769      * 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
 771      * collection's iterator.
 772      *
 773      * @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
 775      * @throws NullPointerException if the specified collection is null
 776      * @see #add(Object)
 777      */
 778     public boolean addAll(Collection<? extends E> c) {
 779         Object[] cs = c.toArray();
 780         if (cs.length == 0)
 781             return false;
 782         final ReentrantLock lock = this.lock;
 783         lock.lock();
 784         try {
 785             Object[] elements = getArray();
 786             int len = elements.length;
 787             Object[] newElements = Arrays.copyOf(elements, len + cs.length);
 788             System.arraycopy(cs, 0, newElements, len, cs.length);
 789             setArray(newElements);
 790             return true;
 791         } finally {
 792             lock.unlock();
 793         }
 794     }
 795 
 796     /**
 797      * Inserts all of the elements in the specified collection into this
 798      * list, starting at the specified position.  Shifts the element
 799      * currently at that position (if any) and any subsequent elements to
 800      * the right (increases their indices).  The new elements will appear
 801      * in this list in the order that they are returned by the
 802      * specified collection's iterator.
 803      *
 804      * @param index index at which to insert the first element
 805      *        from the specified collection
 806      * @param c collection containing elements to be added to this list
 807      * @return <tt>true</tt> if this list changed as a result of the call
 808      * @throws IndexOutOfBoundsException {@inheritDoc}
 809      * @throws NullPointerException if the specified collection is null
 810      * @see #add(int,Object)
 811      */
 812     public boolean addAll(int index, Collection<? extends E> c) {
 813         Object[] cs = c.toArray();
 814         final ReentrantLock lock = this.lock;
 815         lock.lock();
 816         try {
 817             Object[] elements = getArray();
 818             int len = elements.length;
 819             if (index > len || index < 0)
 820                 throw new IndexOutOfBoundsException("Index: "+index+
 821                                                     ", Size: "+len);
 822             if (cs.length == 0)
 823                 return false;
 824             int numMoved = len - index;
 825             Object[] newElements;
 826             if (numMoved == 0)
 827                 newElements = Arrays.copyOf(elements, len + cs.length);
 828             else {
 829                 newElements = new Object[len + cs.length];
 830                 System.arraycopy(elements, 0, newElements, 0, index);
 831                 System.arraycopy(elements, index,
 832                                  newElements, index + cs.length,
 833                                  numMoved);
 834             }
 835             System.arraycopy(cs, 0, newElements, index, cs.length);
 836             setArray(newElements);
 837             return true;
 838         } finally {
 839             lock.unlock();
 840         }
 841     }
 842 
 843     /**
 844      * Saves this list to a stream (that is, serializes it).
 845      *
 846      * @serialData The length of the array backing the list is emitted
 847      *               (int), followed by all of its elements (each an Object)
 848      *               in the proper order.
 849      */
 850     private void writeObject(java.io.ObjectOutputStream s)
 851         throws java.io.IOException {
 852 
 853         s.defaultWriteObject();
 854 
 855         Object[] elements = getArray();
 856         // Write out array length
 857         s.writeInt(elements.length);
 858 
 859         // Write out all elements in the proper order.
 860         for (Object element : elements)
 861             s.writeObject(element);
 862     }
 863 
 864     /**
 865      * Reconstitutes this list from a stream (that is, deserializes it).
 866      */
 867     private void readObject(java.io.ObjectInputStream s)
 868         throws java.io.IOException, ClassNotFoundException {
 869 
 870         s.defaultReadObject();
 871 
 872         // bind to new lock
 873         resetLock();
 874 
 875         // Read in array length and allocate array
 876         int len = s.readInt();
 877         Object[] elements = new Object[len];
 878 
 879         // Read in all elements in the proper order.
 880         for (int i = 0; i < len; i++)
 881             elements[i] = s.readObject();
 882         setArray(elements);
 883     }
 884 
 885     /**
 886      * Returns a string representation of this list.  The string
 887      * representation consists of the string representations of the list's
 888      * elements in the order they are returned by its iterator, enclosed in
 889      * square brackets (<tt>"[]"</tt>).  Adjacent elements are separated by
 890      * the characters <tt>", "</tt> (comma and space).  Elements are
 891      * converted to strings as by {@link String#valueOf(Object)}.
 892      *
 893      * @return a string representation of this list
 894      */
 895     public String toString() {
 896         return Arrays.toString(getArray());
 897     }
 898 
 899     /**
 900      * Compares the specified object with this list for equality.
 901      * Returns {@code true} if the specified object is the same object
 902      * as this object, or if it is also a {@link List} and the sequence
 903      * of elements returned by an {@linkplain List#iterator() iterator}
 904      * over the specified list is the same as the sequence returned by
 905      * an iterator over this list.  The two sequences are considered to
 906      * be the same if they have the same length and corresponding
 907      * elements at the same position in the sequence are <em>equal</em>.
 908      * Two elements {@code e1} and {@code e2} are considered
 909      * <em>equal</em> if {@code (e1==null ? e2==null : e1.equals(e2))}.
 910      *
 911      * @param o the object to be compared for equality with this list
 912      * @return {@code true} if the specified object is equal to this list
 913      */
 914     public boolean equals(Object o) {
 915         if (o == this)
 916             return true;
 917         if (!(o instanceof List))
 918             return false;
 919 
 920         List<?> list = (List<?>)(o);
 921         Iterator<?> it = list.iterator();
 922         Object[] elements = getArray();
 923         int len = elements.length;
 924         for (int i = 0; i < len; ++i)
 925             if (!it.hasNext() || !eq(elements[i], it.next()))
 926                 return false;
 927         if (it.hasNext())
 928             return false;
 929         return true;
 930     }
 931 
 932     /**
 933      * Returns the hash code value for this list.
 934      *
 935      * <p>This implementation uses the definition in {@link List#hashCode}.
 936      *
 937      * @return the hash code value for this list
 938      */
 939     public int hashCode() {
 940         int hashCode = 1;
 941         Object[] elements = getArray();
 942         int len = elements.length;
 943         for (int i = 0; i < len; ++i) {
 944             Object obj = elements[i];
 945             hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
 946         }
 947         return hashCode;
 948     }
 949 
 950     /**
 951      * Returns an iterator over the elements in this list in proper sequence.
 952      *
 953      * <p>The returned iterator provides a snapshot of the state of the list
 954      * when the iterator was constructed. No synchronization is needed while
 955      * traversing the iterator. The iterator does <em>NOT</em> support the
 956      * <tt>remove</tt> method.
 957      *
 958      * @return an iterator over the elements in this list in proper sequence
 959      */
 960     public Iterator<E> iterator() {
 961         return new COWIterator<E>(getArray(), 0);
 962     }
 963 
 964     /**
 965      * {@inheritDoc}
 966      *
 967      * <p>The returned iterator provides a snapshot of the state of the list
 968      * when the iterator was constructed. No synchronization is needed while
 969      * traversing the iterator. The iterator does <em>NOT</em> support the
 970      * <tt>remove</tt>, <tt>set</tt> or <tt>add</tt> methods.
 971      */
 972     public ListIterator<E> listIterator() {
 973         return new COWIterator<E>(getArray(), 0);
 974     }
 975 
 976     /**
 977      * {@inheritDoc}
 978      *
 979      * <p>The returned iterator provides a snapshot of the state of the list
 980      * when the iterator was constructed. No synchronization is needed while
 981      * traversing the iterator. The iterator does <em>NOT</em> support the
 982      * <tt>remove</tt>, <tt>set</tt> or <tt>add</tt> methods.
 983      *
 984      * @throws IndexOutOfBoundsException {@inheritDoc}
 985      */
 986     public ListIterator<E> listIterator(final int index) {
 987         Object[] elements = getArray();
 988         int len = elements.length;
 989         if (index<0 || index>len)
 990             throw new IndexOutOfBoundsException("Index: "+index);
 991 
 992         return new COWIterator<E>(elements, index);
 993     }
 994 
 995     private static class COWIterator<E> implements ListIterator<E> {
 996         /** Snapshot of the array */
 997         private final Object[] snapshot;
 998         /** Index of element to be returned by subsequent call to next.  */
 999         private int cursor;
1000 
1001         private COWIterator(Object[] elements, int initialCursor) {
1002             cursor = initialCursor;
1003             snapshot = elements;
1004         }
1005 
1006         public boolean hasNext() {
1007             return cursor < snapshot.length;
1008         }
1009 
1010         public boolean hasPrevious() {
1011             return cursor > 0;
1012         }
1013 
1014         @SuppressWarnings("unchecked")
1015         public E next() {
1016             if (! hasNext())
1017                 throw new NoSuchElementException();
1018             return (E) snapshot[cursor++];
1019         }
1020 
1021         @SuppressWarnings("unchecked")
1022         public E previous() {
1023             if (! hasPrevious())
1024                 throw new NoSuchElementException();
1025             return (E) snapshot[--cursor];
1026         }
1027 
1028         public int nextIndex() {
1029             return cursor;
1030         }
1031 
1032         public int previousIndex() {
1033             return cursor-1;
1034         }
1035 
1036         /**
1037          * Not supported. Always throws UnsupportedOperationException.
1038          * @throws UnsupportedOperationException always; <tt>remove</tt>
1039          *         is not supported by this iterator.
1040          */
1041         public void remove() {
1042             throw new UnsupportedOperationException();
1043         }
1044 
1045         /**
1046          * Not supported. Always throws UnsupportedOperationException.
1047          * @throws UnsupportedOperationException always; <tt>set</tt>
1048          *         is not supported by this iterator.
1049          */
1050         public void set(E e) {
1051             throw new UnsupportedOperationException();
1052         }
1053 
1054         /**
1055          * Not supported. Always throws UnsupportedOperationException.
1056          * @throws UnsupportedOperationException always; <tt>add</tt>
1057          *         is not supported by this iterator.
1058          */
1059         public void add(E e) {
1060             throw new UnsupportedOperationException();
1061         }
1062 
1063         @Override
1064         @SuppressWarnings("unchecked")
1065         public void forEachRemaining(Consumer<? super E> action) {
1066             Objects.requireNonNull(action);
1067             final int size = snapshot.length;
1068             for (int i=cursor; i < size; i++) {
1069                 action.accept((E) snapshot[i]);
1070             }
1071             cursor = size;
1072         }
1073     }
1074 
1075     /**
1076      * Returns a view of the portion of this list between
1077      * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
1078      * The returned list is backed by this list, so changes in the
1079      * returned list are reflected in this list.
1080      *
1081      * <p>The semantics of the list returned by this method become
1082      * undefined if the backing list (i.e., this list) is modified in
1083      * any way other than via the returned list.
1084      *
1085      * @param fromIndex low endpoint (inclusive) of the subList
1086      * @param toIndex high endpoint (exclusive) of the subList
1087      * @return a view of the specified range within this list
1088      * @throws IndexOutOfBoundsException {@inheritDoc}
1089      */
1090     public List<E> subList(int fromIndex, int toIndex) {
1091         final ReentrantLock lock = this.lock;
1092         lock.lock();
1093         try {
1094             Object[] elements = getArray();
1095             int len = elements.length;
1096             if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
1097                 throw new IndexOutOfBoundsException();
1098             return new COWSubList<E>(this, fromIndex, toIndex);
1099         } finally {
1100             lock.unlock();
1101         }
1102     }
1103 
1104     /**
1105      * Sublist for CopyOnWriteArrayList.
1106      * This class extends AbstractList merely for convenience, to
1107      * avoid having to define addAll, etc. This doesn't hurt, but
1108      * is wasteful.  This class does not need or use modCount
1109      * mechanics in AbstractList, but does need to check for
1110      * concurrent modification using similar mechanics.  On each
1111      * operation, the array that we expect the backing list to use
1112      * is checked and updated.  Since we do this for all of the
1113      * base operations invoked by those defined in AbstractList,
1114      * all is well.  While inefficient, this is not worth
1115      * improving.  The kinds of list operations inherited from
1116      * AbstractList are already so slow on COW sublists that
1117      * adding a bit more space/time doesn't seem even noticeable.
1118      */
1119     private static class COWSubList<E>
1120         extends AbstractList<E>
1121         implements RandomAccess
1122     {
1123         private final CopyOnWriteArrayList<E> l;
1124         private final int offset;
1125         private int size;
1126         private Object[] expectedArray;
1127 
1128         // only call this holding l's lock
1129         COWSubList(CopyOnWriteArrayList<E> list,
1130                    int fromIndex, int toIndex) {
1131             l = list;
1132             expectedArray = l.getArray();
1133             offset = fromIndex;
1134             size = toIndex - fromIndex;
1135         }
1136 
1137         // only call this holding l's lock
1138         private void checkForComodification() {
1139             if (l.getArray() != expectedArray)
1140                 throw new ConcurrentModificationException();
1141         }
1142 
1143         // only call this holding l's lock
1144         private void rangeCheck(int index) {
1145             if (index<0 || index>=size)
1146                 throw new IndexOutOfBoundsException("Index: "+index+
1147                                                     ",Size: "+size);
1148         }
1149 
1150         public E set(int index, E element) {
1151             final ReentrantLock lock = l.lock;
1152             lock.lock();
1153             try {
1154                 rangeCheck(index);
1155                 checkForComodification();
1156                 E x = l.set(index+offset, element);
1157                 expectedArray = l.getArray();
1158                 return x;
1159             } finally {
1160                 lock.unlock();
1161             }
1162         }
1163 
1164         public E get(int index) {
1165             final ReentrantLock lock = l.lock;
1166             lock.lock();
1167             try {
1168                 rangeCheck(index);
1169                 checkForComodification();
1170                 return l.get(index+offset);
1171             } finally {
1172                 lock.unlock();
1173             }
1174         }
1175 
1176         public int size() {
1177             final ReentrantLock lock = l.lock;
1178             lock.lock();
1179             try {
1180                 checkForComodification();
1181                 return size;
1182             } finally {
1183                 lock.unlock();
1184             }
1185         }
1186 
1187         public void add(int index, E element) {
1188             final ReentrantLock lock = l.lock;
1189             lock.lock();
1190             try {
1191                 checkForComodification();
1192                 if (index<0 || index>size)
1193                     throw new IndexOutOfBoundsException();
1194                 l.add(index+offset, element);
1195                 expectedArray = l.getArray();
1196                 size++;
1197             } finally {
1198                 lock.unlock();
1199             }
1200         }
1201 
1202         public void clear() {
1203             final ReentrantLock lock = l.lock;
1204             lock.lock();
1205             try {
1206                 checkForComodification();
1207                 l.removeRange(offset, offset+size);
1208                 expectedArray = l.getArray();
1209                 size = 0;
1210             } finally {
1211                 lock.unlock();
1212             }
1213         }
1214 
1215         public E remove(int index) {
1216             final ReentrantLock lock = l.lock;
1217             lock.lock();
1218             try {
1219                 rangeCheck(index);
1220                 checkForComodification();
1221                 E result = l.remove(index+offset);
1222                 expectedArray = l.getArray();
1223                 size--;
1224                 return result;
1225             } finally {
1226                 lock.unlock();
1227             }
1228         }
1229 
1230         public boolean remove(Object o) {
1231             int index = indexOf(o);
1232             if (index == -1)
1233                 return false;
1234             remove(index);
1235             return true;
1236         }
1237 
1238         public Iterator<E> iterator() {
1239             final ReentrantLock lock = l.lock;
1240             lock.lock();
1241             try {
1242                 checkForComodification();
1243                 return new COWSubListIterator<E>(l, 0, offset, size);
1244             } finally {
1245                 lock.unlock();
1246             }
1247         }
1248 
1249         public ListIterator<E> listIterator(final int index) {
1250             final ReentrantLock lock = l.lock;
1251             lock.lock();
1252             try {
1253                 checkForComodification();
1254                 if (index<0 || index>size)
1255                     throw new IndexOutOfBoundsException("Index: "+index+
1256                                                         ", Size: "+size);
1257                 return new COWSubListIterator<E>(l, index, offset, size);
1258             } finally {
1259                 lock.unlock();
1260             }
1261         }
1262 
1263         public List<E> subList(int fromIndex, int toIndex) {
1264             final ReentrantLock lock = l.lock;
1265             lock.lock();
1266             try {
1267                 checkForComodification();
1268                 if (fromIndex<0 || toIndex>size)
1269                     throw new IndexOutOfBoundsException();
1270                 return new COWSubList<E>(l, fromIndex + offset,
1271                                          toIndex + offset);
1272             } finally {
1273                 lock.unlock();
1274             }
1275         }
1276 
1277         @Override
1278         public void forEach(Consumer<? super E> action) {
1279             @SuppressWarnings("unchecked")
1280             final E[] elements = (E[]) l.getArray();
1281             checkForComodification();
1282             l.forEach(action, elements, offset, offset + size);
1283         }
1284 
1285         @Override
1286         public void sort(Comparator<? super E> c) {
1287             final ReentrantLock lock = l.lock;
1288             lock.lock();
1289             try {
1290                 checkForComodification();
1291                 l.sort(c, offset, offset + size);
1292                 expectedArray = l.getArray();
1293             } finally {
1294                 lock.unlock();
1295             }
1296         }
1297 
1298         @Override
1299         public boolean removeIf(Predicate<? super E> filter) {
1300             Objects.requireNonNull(filter);
1301             final ReentrantLock lock = l.lock;
1302             lock.lock();
1303             try {
1304                 checkForComodification();
1305                 final int removeCount =
1306                         l.removeIf(filter, offset, offset + size);
1307                 expectedArray = l.getArray();
1308                 size -= removeCount;
1309                 return removeCount > 0;
1310             } finally {
1311                 lock.unlock();
1312             }
1313         }
1314 
1315         @Override
1316         public void replaceAll(UnaryOperator<E> operator) {
1317             final ReentrantLock lock = l.lock;
1318             lock.lock();
1319             try {
1320                 checkForComodification();
1321                 l.replaceAll(operator, offset, offset + size);
1322                 expectedArray = l.getArray();
1323             } finally {
1324                 lock.unlock();
1325             }
1326         }
1327     }
1328 
1329     private static class COWSubListIterator<E> implements ListIterator<E> {
1330         private final ListIterator<E> it;
1331         private final int offset;
1332         private final int size;
1333 
1334         COWSubListIterator(List<E> l, int index, int offset, int size) {
1335             this.offset = offset;
1336             this.size = size;
1337             it = l.listIterator(index+offset);
1338         }
1339 
1340         public boolean hasNext() {
1341             return nextIndex() < size;
1342         }
1343 
1344         public E next() {
1345             if (hasNext())
1346                 return it.next();
1347             else
1348                 throw new NoSuchElementException();
1349         }
1350 
1351         public boolean hasPrevious() {
1352             return previousIndex() >= 0;
1353         }
1354 
1355         public E previous() {
1356             if (hasPrevious())
1357                 return it.previous();
1358             else
1359                 throw new NoSuchElementException();
1360         }
1361 
1362         public int nextIndex() {
1363             return it.nextIndex() - offset;
1364         }
1365 
1366         public int previousIndex() {
1367             return it.previousIndex() - offset;
1368         }
1369 
1370         public void remove() {
1371             throw new UnsupportedOperationException();
1372         }
1373 
1374         public void set(E e) {
1375             throw new UnsupportedOperationException();
1376         }
1377 
1378         public void add(E e) {
1379             throw new UnsupportedOperationException();
1380         }
1381 
1382         @Override
1383         @SuppressWarnings("unchecked")
1384         public void forEachRemaining(Consumer<? super E> action) {
1385             Objects.requireNonNull(action);
1386             while (nextIndex() < size) {
1387                 action.accept(it.next());
1388             }
1389         }
1390     }
1391 
1392     // Support for resetting lock while deserializing
1393     private void resetLock() {
1394         UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock());
1395     }
1396     private static final sun.misc.Unsafe UNSAFE;
1397     private static final long lockOffset;
1398     static {
1399         try {
1400             UNSAFE = sun.misc.Unsafe.getUnsafe();
1401             Class<?> k = CopyOnWriteArrayList.class;
1402             lockOffset = UNSAFE.objectFieldOffset
1403                 (k.getDeclaredField("lock"));
1404         } catch (Exception e) {
1405             throw new Error(e);
1406         }
1407     }
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 }