1 /*
   2  * Copyright (c) 1997, 2019, 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 package java.util;
  27 
  28 import java.util.function.Consumer;
  29 import java.util.function.Predicate;
  30 import java.util.function.UnaryOperator;
  31 import jdk.internal.access.SharedSecrets;
  32 import jdk.internal.util.ArraysSupport;
  33 
  34 /**
  35  * Resizable-array implementation of the {@code List} interface.  Implements
  36  * all optional list operations, and permits all elements, including
  37  * {@code null}.  In addition to implementing the {@code List} interface,
  38  * this class provides methods to manipulate the size of the array that is
  39  * used internally to store the list.  (This class is roughly equivalent to
  40  * {@code Vector}, except that it is unsynchronized.)
  41  *
  42  * <p>The {@code size}, {@code isEmpty}, {@code get}, {@code set},
  43  * {@code iterator}, and {@code listIterator} operations run in constant
  44  * time.  The {@code add} operation runs in <i>amortized constant time</i>,
  45  * that is, adding n elements requires O(n) time.  All of the other operations
  46  * run in linear time (roughly speaking).  The constant factor is low compared
  47  * to that for the {@code LinkedList} implementation.
  48  *
  49  * <p>Each {@code ArrayList} instance has a <i>capacity</i>.  The capacity is
  50  * the size of the array used to store the elements in the list.  It is always
  51  * at least as large as the list size.  As elements are added to an ArrayList,
  52  * its capacity grows automatically.  The details of the growth policy are not
  53  * specified beyond the fact that adding an element has constant amortized
  54  * time cost.
  55  *
  56  * <p>An application can increase the capacity of an {@code ArrayList} instance
  57  * before adding a large number of elements using the {@code ensureCapacity}
  58  * operation.  This may reduce the amount of incremental reallocation.
  59  *
  60  * <p><strong>Note that this implementation is not synchronized.</strong>
  61  * If multiple threads access an {@code ArrayList} instance concurrently,
  62  * and at least one of the threads modifies the list structurally, it
  63  * <i>must</i> be synchronized externally.  (A structural modification is
  64  * any operation that adds or deletes one or more elements, or explicitly
  65  * resizes the backing array; merely setting the value of an element is not
  66  * a structural modification.)  This is typically accomplished by
  67  * synchronizing on some object that naturally encapsulates the list.
  68  *
  69  * If no such object exists, the list should be "wrapped" using the
  70  * {@link Collections#synchronizedList Collections.synchronizedList}
  71  * method.  This is best done at creation time, to prevent accidental
  72  * unsynchronized access to the list:<pre>
  73  *   List list = Collections.synchronizedList(new ArrayList(...));</pre>
  74  *
  75  * <p id="fail-fast">
  76  * The iterators returned by this class's {@link #iterator() iterator} and
  77  * {@link #listIterator(int) listIterator} methods are <em>fail-fast</em>:
  78  * if the list is structurally modified at any time after the iterator is
  79  * created, in any way except through the iterator's own
  80  * {@link ListIterator#remove() remove} or
  81  * {@link ListIterator#add(Object) add} methods, the iterator will throw a
  82  * {@link ConcurrentModificationException}.  Thus, in the face of
  83  * concurrent modification, the iterator fails quickly and cleanly, rather
  84  * than risking arbitrary, non-deterministic behavior at an undetermined
  85  * time in the future.
  86  *
  87  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  88  * as it is, generally speaking, impossible to make any hard guarantees in the
  89  * presence of unsynchronized concurrent modification.  Fail-fast iterators
  90  * throw {@code ConcurrentModificationException} on a best-effort basis.
  91  * Therefore, it would be wrong to write a program that depended on this
  92  * exception for its correctness:  <i>the fail-fast behavior of iterators
  93  * should be used only to detect bugs.</i>
  94  *
  95  * <p>This class is a member of the
  96  * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  97  * Java Collections Framework</a>.
  98  *
  99  * @param <E> the type of elements in this list
 100  *
 101  * @author  Josh Bloch
 102  * @author  Neal Gafter
 103  * @see     Collection
 104  * @see     List
 105  * @see     LinkedList
 106  * @see     Vector
 107  * @since   1.2
 108  */
 109 public class ArrayList<E> extends AbstractList<E>
 110         implements List<E>, RandomAccess, Cloneable, java.io.Serializable
 111 {
 112     @java.io.Serial
 113     private static final long serialVersionUID = 8683452581122892189L;
 114 
 115     /**
 116      * Default initial capacity.
 117      */
 118     private static final int DEFAULT_CAPACITY = 10;
 119 
 120     /**
 121      * Shared empty array instance used for empty instances.
 122      */
 123     private static final Object[] EMPTY_ELEMENTDATA = {};
 124 
 125     /**
 126      * Shared empty array instance used for default sized empty instances. We
 127      * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
 128      * first element is added.
 129      */
 130     private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
 131 
 132     /**
 133      * The array buffer into which the elements of the ArrayList are stored.
 134      * The capacity of the ArrayList is the length of this array buffer. Any
 135      * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
 136      * will be expanded to DEFAULT_CAPACITY when the first element is added.
 137      */
 138     transient Object[] elementData; // non-private to simplify nested class access
 139 
 140     /**
 141      * The size of the ArrayList (the number of elements it contains).
 142      *
 143      * @serial
 144      */
 145     private int size;
 146 
 147     /**
 148      * Constructs an empty list with the specified initial capacity.
 149      *
 150      * @param  initialCapacity  the initial capacity of the list
 151      * @throws IllegalArgumentException if the specified initial capacity
 152      *         is negative
 153      */
 154     public ArrayList(int initialCapacity) {
 155         if (initialCapacity > 0) {
 156             this.elementData = new Object[initialCapacity];
 157         } else if (initialCapacity == 0) {
 158             this.elementData = EMPTY_ELEMENTDATA;
 159         } else {
 160             throw new IllegalArgumentException("Illegal Capacity: "+
 161                                                initialCapacity);
 162         }
 163     }
 164 
 165     /**
 166      * Constructs an empty list with an initial capacity of ten.
 167      */
 168     public ArrayList() {
 169         this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
 170     }
 171 
 172     /**
 173      * Constructs a list containing the elements of the specified
 174      * collection, in the order they are returned by the collection's
 175      * iterator.
 176      *
 177      * @param c the collection whose elements are to be placed into this list
 178      * @throws NullPointerException if the specified collection is null
 179      */
 180     public ArrayList(Collection<? extends E> c) {
 181         elementData = c.toArray();
 182         if ((size = elementData.length) != 0) {
 183             // defend against c.toArray (incorrectly) not returning Object[]
 184             // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
 185             if (elementData.getClass() != Object[].class)
 186                 elementData = Arrays.copyOf(elementData, size, Object[].class);
 187         } else {
 188             // replace with empty array.
 189             this.elementData = EMPTY_ELEMENTDATA;
 190         }
 191     }
 192 
 193     /**
 194      * Trims the capacity of this {@code ArrayList} instance to be the
 195      * list's current size.  An application can use this operation to minimize
 196      * the storage of an {@code ArrayList} instance.
 197      */
 198     public void trimToSize() {
 199         modCount++;
 200         if (size < elementData.length) {
 201             elementData = (size == 0)
 202               ? EMPTY_ELEMENTDATA
 203               : Arrays.copyOf(elementData, size);
 204         }
 205     }
 206 
 207     /**
 208      * Increases the capacity of this {@code ArrayList} instance, if
 209      * necessary, to ensure that it can hold at least the number of elements
 210      * specified by the minimum capacity argument.
 211      *
 212      * @param minCapacity the desired minimum capacity
 213      */
 214     public void ensureCapacity(int minCapacity) {
 215         if (minCapacity > elementData.length
 216             && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
 217                  && minCapacity <= DEFAULT_CAPACITY)) {
 218             modCount++;
 219             grow(minCapacity);
 220         }
 221     }
 222 
 223     /**
 224      * Increases the capacity to ensure that it can hold at least the
 225      * number of elements specified by the minimum capacity argument.
 226      *
 227      * @param minCapacity the desired minimum capacity
 228      * @throws OutOfMemoryError if minCapacity is less than zero
 229      */
 230     private Object[] grow(int minCapacity) {
 231         int oldCapacity = elementData.length;
 232         if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
 233             int newCapacity = ArraysSupport.newLength(oldCapacity,
 234                     minCapacity - oldCapacity, /* minimum growth */
 235                     oldCapacity >> 1           /* preferred growth */);
 236             return elementData = Arrays.copyOf(elementData, newCapacity);
 237         } else {
 238             return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
 239         }
 240     }
 241 
 242     private Object[] grow() {
 243         return grow(size + 1);
 244     }
 245 
 246     /**
 247      * Returns the number of elements in this list.
 248      *
 249      * @return the number of elements in this list
 250      */
 251     public int size() {
 252         return size;
 253     }
 254 
 255     /**
 256      * Returns {@code true} if this list contains no elements.
 257      *
 258      * @return {@code true} if this list contains no elements
 259      */
 260     public boolean isEmpty() {
 261         return size == 0;
 262     }
 263 
 264     /**
 265      * Returns {@code true} if this list contains the specified element.
 266      * More formally, returns {@code true} if and only if this list contains
 267      * at least one element {@code e} such that
 268      * {@code Objects.equals(o, e)}.
 269      *
 270      * @param o element whose presence in this list is to be tested
 271      * @return {@code true} if this list contains the specified element
 272      */
 273     public boolean contains(Object o) {
 274         return indexOf(o) >= 0;
 275     }
 276 
 277     /**
 278      * Returns the index of the first occurrence of the specified element
 279      * in this list, or -1 if this list does not contain the element.
 280      * More formally, returns the lowest index {@code i} such that
 281      * {@code Objects.equals(o, get(i))},
 282      * or -1 if there is no such index.
 283      */
 284     public int indexOf(Object o) {
 285         return indexOfRange(o, 0, size);
 286     }
 287 
 288     int indexOfRange(Object o, int start, int end) {
 289         Object[] es = elementData;
 290         if (o == null) {
 291             for (int i = start; i < end; i++) {
 292                 if (es[i] == null) {
 293                     return i;
 294                 }
 295             }
 296         } else {
 297             for (int i = start; i < end; i++) {
 298                 if (o.equals(es[i])) {
 299                     return i;
 300                 }
 301             }
 302         }
 303         return -1;
 304     }
 305 
 306     /**
 307      * Returns the index of the last occurrence of the specified element
 308      * in this list, or -1 if this list does not contain the element.
 309      * More formally, returns the highest index {@code i} such that
 310      * {@code Objects.equals(o, get(i))},
 311      * or -1 if there is no such index.
 312      */
 313     public int lastIndexOf(Object o) {
 314         return lastIndexOfRange(o, 0, size);
 315     }
 316 
 317     int lastIndexOfRange(Object o, int start, int end) {
 318         Object[] es = elementData;
 319         if (o == null) {
 320             for (int i = end - 1; i >= start; i--) {
 321                 if (es[i] == null) {
 322                     return i;
 323                 }
 324             }
 325         } else {
 326             for (int i = end - 1; i >= start; i--) {
 327                 if (o.equals(es[i])) {
 328                     return i;
 329                 }
 330             }
 331         }
 332         return -1;
 333     }
 334 
 335     /**
 336      * Returns a shallow copy of this {@code ArrayList} instance.  (The
 337      * elements themselves are not copied.)
 338      *
 339      * @return a clone of this {@code ArrayList} instance
 340      */
 341     public Object clone() {
 342         try {
 343             ArrayList<?> v = (ArrayList<?>) super.clone();
 344             v.elementData = Arrays.copyOf(elementData, size);
 345             v.modCount = 0;
 346             return v;
 347         } catch (CloneNotSupportedException e) {
 348             // this shouldn't happen, since we are Cloneable
 349             throw new InternalError(e);
 350         }
 351     }
 352 
 353     /**
 354      * Returns an array containing all of the elements in this list
 355      * in proper sequence (from first to last element).
 356      *
 357      * <p>The returned array will be "safe" in that no references to it are
 358      * maintained by this list.  (In other words, this method must allocate
 359      * a new array).  The caller is thus free to modify the returned array.
 360      *
 361      * <p>This method acts as bridge between array-based and collection-based
 362      * APIs.
 363      *
 364      * @return an array containing all of the elements in this list in
 365      *         proper sequence
 366      */
 367     public Object[] toArray() {
 368         return Arrays.copyOf(elementData, size);
 369     }
 370 
 371     /**
 372      * Returns an array containing all of the elements in this list in proper
 373      * sequence (from first to last element); the runtime type of the returned
 374      * array is that of the specified array.  If the list fits in the
 375      * specified array, it is returned therein.  Otherwise, a new array is
 376      * allocated with the runtime type of the specified array and the size of
 377      * this list.
 378      *
 379      * <p>If the list fits in the specified array with room to spare
 380      * (i.e., the array has more elements than the list), the element in
 381      * the array immediately following the end of the collection is set to
 382      * {@code null}.  (This is useful in determining the length of the
 383      * list <i>only</i> if the caller knows that the list does not contain
 384      * any null elements.)
 385      *
 386      * @param a the array into which the elements of the list are to
 387      *          be stored, if it is big enough; otherwise, a new array of the
 388      *          same runtime type is allocated for this purpose.
 389      * @return an array containing the elements of the list
 390      * @throws ArrayStoreException if the runtime type of the specified array
 391      *         is not a supertype of the runtime type of every element in
 392      *         this list
 393      * @throws NullPointerException if the specified array is null
 394      */
 395     @SuppressWarnings("unchecked")
 396     public <T> T[] toArray(T[] a) {
 397         if (a.length < size)
 398             // Make a new array of a's runtime type, but my contents:
 399             return (T[]) Arrays.copyOf(elementData, size, a.getClass());
 400         System.arraycopy(elementData, 0, a, 0, size);
 401         if (a.length > size)
 402             a[size] = null;
 403         return a;
 404     }
 405 
 406     // Positional Access Operations
 407 
 408     @SuppressWarnings("unchecked")
 409     E elementData(int index) {
 410         return (E) elementData[index];
 411     }
 412 
 413     @SuppressWarnings("unchecked")
 414     static <E> E elementAt(Object[] es, int index) {
 415         return (E) es[index];
 416     }
 417 
 418     /**
 419      * Returns the element at the specified position in this list.
 420      *
 421      * @param  index index of the element to return
 422      * @return the element at the specified position in this list
 423      * @throws IndexOutOfBoundsException {@inheritDoc}
 424      */
 425     public E get(int index) {
 426         Objects.checkIndex(index, size);
 427         return elementData(index);
 428     }
 429 
 430     /**
 431      * Replaces the element at the specified position in this list with
 432      * the specified element.
 433      *
 434      * @param index index of the element to replace
 435      * @param element element to be stored at the specified position
 436      * @return the element previously at the specified position
 437      * @throws IndexOutOfBoundsException {@inheritDoc}
 438      */
 439     public E set(int index, E element) {
 440         Objects.checkIndex(index, size);
 441         E oldValue = elementData(index);
 442         elementData[index] = element;
 443         return oldValue;
 444     }
 445 
 446     /**
 447      * This helper method split out from add(E) to keep method
 448      * bytecode size under 35 (the -XX:MaxInlineSize default value),
 449      * which helps when add(E) is called in a C1-compiled loop.
 450      */
 451     private void add(E e, Object[] elementData, int s) {
 452         if (s == elementData.length)
 453             elementData = grow();
 454         elementData[s] = e;
 455         size = s + 1;
 456     }
 457 
 458     /**
 459      * Appends the specified element to the end of this list.
 460      *
 461      * @param e element to be appended to this list
 462      * @return {@code true} (as specified by {@link Collection#add})
 463      */
 464     public boolean add(E e) {
 465         modCount++;
 466         add(e, elementData, size);
 467         return true;
 468     }
 469 
 470     /**
 471      * Inserts the specified element at the specified position in this
 472      * list. Shifts the element currently at that position (if any) and
 473      * any subsequent elements to the right (adds one to their indices).
 474      *
 475      * @param index index at which the specified element is to be inserted
 476      * @param element element to be inserted
 477      * @throws IndexOutOfBoundsException {@inheritDoc}
 478      */
 479     public void add(int index, E element) {
 480         rangeCheckForAdd(index);
 481         modCount++;
 482         final int s;
 483         Object[] elementData;
 484         if ((s = size) == (elementData = this.elementData).length)
 485             elementData = grow();
 486         System.arraycopy(elementData, index,
 487                          elementData, index + 1,
 488                          s - index);
 489         elementData[index] = element;
 490         size = s + 1;
 491     }
 492 
 493     /**
 494      * Removes the element at the specified position in this list.
 495      * Shifts any subsequent elements to the left (subtracts one from their
 496      * indices).
 497      *
 498      * @param index the index of the element to be removed
 499      * @return the element that was removed from the list
 500      * @throws IndexOutOfBoundsException {@inheritDoc}
 501      */
 502     public E remove(int index) {
 503         Objects.checkIndex(index, size);
 504         final Object[] es = elementData;
 505 
 506         @SuppressWarnings("unchecked") E oldValue = (E) es[index];
 507         fastRemove(es, index);
 508 
 509         return oldValue;
 510     }
 511 
 512     /**
 513      * {@inheritDoc}
 514      */
 515     public boolean equals(Object o) {
 516         if (o == this) {
 517             return true;
 518         }
 519 
 520         if (!(o instanceof List)) {
 521             return false;
 522         }
 523 
 524         final int expectedModCount = modCount;
 525         // ArrayList can be subclassed and given arbitrary behavior, but we can
 526         // still deal with the common case where o is ArrayList precisely
 527         boolean equal = (o.getClass() == ArrayList.class)
 528             ? equalsArrayList((ArrayList<?>) o)
 529             : equalsRange((List<?>) o, 0, size);
 530 
 531         checkForComodification(expectedModCount);
 532         return equal;
 533     }
 534 
 535     boolean equalsRange(List<?> other, int from, int to) {
 536         final Object[] es = elementData;
 537         if (to > es.length) {
 538             throw new ConcurrentModificationException();
 539         }
 540         var oit = other.iterator();
 541         for (; from < to; from++) {
 542             if (!oit.hasNext() || !Objects.equals(es[from], oit.next())) {
 543                 return false;
 544             }
 545         }
 546         return !oit.hasNext();
 547     }
 548 
 549     private boolean equalsArrayList(ArrayList<?> other) {
 550         final int otherModCount = other.modCount;
 551         final int s = size;
 552         boolean equal;
 553         if (equal = (s == other.size)) {
 554             final Object[] otherEs = other.elementData;
 555             final Object[] es = elementData;
 556             if (s > es.length || s > otherEs.length) {
 557                 throw new ConcurrentModificationException();
 558             }
 559             for (int i = 0; i < s; i++) {
 560                 if (!Objects.equals(es[i], otherEs[i])) {
 561                     equal = false;
 562                     break;
 563                 }
 564             }
 565         }
 566         other.checkForComodification(otherModCount);
 567         return equal;
 568     }
 569 
 570     private void checkForComodification(final int expectedModCount) {
 571         if (modCount != expectedModCount) {
 572             throw new ConcurrentModificationException();
 573         }
 574     }
 575 
 576     /**
 577      * {@inheritDoc}
 578      */
 579     public int hashCode() {
 580         int expectedModCount = modCount;
 581         int hash = hashCodeRange(0, size);
 582         checkForComodification(expectedModCount);
 583         return hash;
 584     }
 585 
 586     int hashCodeRange(int from, int to) {
 587         final Object[] es = elementData;
 588         if (to > es.length) {
 589             throw new ConcurrentModificationException();
 590         }
 591         int hashCode = 1;
 592         for (int i = from; i < to; i++) {
 593             Object e = es[i];
 594             hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
 595         }
 596         return hashCode;
 597     }
 598 
 599     /**
 600      * Removes the first occurrence of the specified element from this list,
 601      * if it is present.  If the list does not contain the element, it is
 602      * unchanged.  More formally, removes the element with the lowest index
 603      * {@code i} such that
 604      * {@code Objects.equals(o, get(i))}
 605      * (if such an element exists).  Returns {@code true} if this list
 606      * contained the specified element (or equivalently, if this list
 607      * changed as a result of the call).
 608      *
 609      * @param o element to be removed from this list, if present
 610      * @return {@code true} if this list contained the specified element
 611      */
 612     public boolean remove(Object o) {
 613         final Object[] es = elementData;
 614         final int size = this.size;
 615         int i = 0;
 616         found: {
 617             if (o == null) {
 618                 for (; i < size; i++)
 619                     if (es[i] == null)
 620                         break found;
 621             } else {
 622                 for (; i < size; i++)
 623                     if (o.equals(es[i]))
 624                         break found;
 625             }
 626             return false;
 627         }
 628         fastRemove(es, i);
 629         return true;
 630     }
 631 
 632     /**
 633      * Private remove method that skips bounds checking and does not
 634      * return the value removed.
 635      */
 636     private void fastRemove(Object[] es, int i) {
 637         modCount++;
 638         final int newSize;
 639         if ((newSize = size - 1) > i)
 640             System.arraycopy(es, i + 1, es, i, newSize - i);
 641         es[size = newSize] = null;
 642     }
 643 
 644     /**
 645      * Removes all of the elements from this list.  The list will
 646      * be empty after this call returns.
 647      */
 648     public void clear() {
 649         modCount++;
 650         final Object[] es = elementData;
 651         for (int to = size, i = size = 0; i < to; i++)
 652             es[i] = null;
 653     }
 654 
 655     /**
 656      * Appends all of the elements in the specified collection to the end of
 657      * this list, in the order that they are returned by the
 658      * specified collection's Iterator.  The behavior of this operation is
 659      * undefined if the specified collection is modified while the operation
 660      * is in progress.  (This implies that the behavior of this call is
 661      * undefined if the specified collection is this list, and this
 662      * list is nonempty.)
 663      *
 664      * @param c collection containing elements to be added to this list
 665      * @return {@code true} if this list changed as a result of the call
 666      * @throws NullPointerException if the specified collection is null
 667      */
 668     public boolean addAll(Collection<? extends E> c) {
 669         Object[] a = c.toArray();
 670         modCount++;
 671         int numNew = a.length;
 672         if (numNew == 0)
 673             return false;
 674         Object[] elementData;
 675         final int s;
 676         if (numNew > (elementData = this.elementData).length - (s = size))
 677             elementData = grow(s + numNew);
 678         System.arraycopy(a, 0, elementData, s, numNew);
 679         size = s + numNew;
 680         return true;
 681     }
 682 
 683     /**
 684      * Inserts all of the elements in the specified collection into this
 685      * list, starting at the specified position.  Shifts the element
 686      * currently at that position (if any) and any subsequent elements to
 687      * the right (increases their indices).  The new elements will appear
 688      * in the list in the order that they are returned by the
 689      * specified collection's iterator.
 690      *
 691      * @param index index at which to insert the first element from the
 692      *              specified collection
 693      * @param c collection containing elements to be added to this list
 694      * @return {@code true} if this list changed as a result of the call
 695      * @throws IndexOutOfBoundsException {@inheritDoc}
 696      * @throws NullPointerException if the specified collection is null
 697      */
 698     public boolean addAll(int index, Collection<? extends E> c) {
 699         rangeCheckForAdd(index);
 700 
 701         Object[] a = c.toArray();
 702         modCount++;
 703         int numNew = a.length;
 704         if (numNew == 0)
 705             return false;
 706         Object[] elementData;
 707         final int s;
 708         if (numNew > (elementData = this.elementData).length - (s = size))
 709             elementData = grow(s + numNew);
 710 
 711         int numMoved = s - index;
 712         if (numMoved > 0)
 713             System.arraycopy(elementData, index,
 714                              elementData, index + numNew,
 715                              numMoved);
 716         System.arraycopy(a, 0, elementData, index, numNew);
 717         size = s + numNew;
 718         return true;
 719     }
 720 
 721     /**
 722      * Removes from this list all of the elements whose index is between
 723      * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
 724      * Shifts any succeeding elements to the left (reduces their index).
 725      * This call shortens the list by {@code (toIndex - fromIndex)} elements.
 726      * (If {@code toIndex==fromIndex}, this operation has no effect.)
 727      *
 728      * @throws IndexOutOfBoundsException if {@code fromIndex} or
 729      *         {@code toIndex} is out of range
 730      *         ({@code fromIndex < 0 ||
 731      *          toIndex > size() ||
 732      *          toIndex < fromIndex})
 733      */
 734     protected void removeRange(int fromIndex, int toIndex) {
 735         if (fromIndex > toIndex) {
 736             throw new IndexOutOfBoundsException(
 737                     outOfBoundsMsg(fromIndex, toIndex));
 738         }
 739         modCount++;
 740         shiftTailOverGap(elementData, fromIndex, toIndex);
 741     }
 742 
 743     /** Erases the gap from lo to hi, by sliding down following elements. */
 744     private void shiftTailOverGap(Object[] es, int lo, int hi) {
 745         System.arraycopy(es, hi, es, lo, size - hi);
 746         for (int to = size, i = (size -= hi - lo); i < to; i++)
 747             es[i] = null;
 748     }
 749 
 750     /**
 751      * A version of rangeCheck used by add and addAll.
 752      */
 753     private void rangeCheckForAdd(int index) {
 754         if (index > size || index < 0)
 755             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
 756     }
 757 
 758     /**
 759      * Constructs an IndexOutOfBoundsException detail message.
 760      * Of the many possible refactorings of the error handling code,
 761      * this "outlining" performs best with both server and client VMs.
 762      */
 763     private String outOfBoundsMsg(int index) {
 764         return "Index: "+index+", Size: "+size;
 765     }
 766 
 767     /**
 768      * A version used in checking (fromIndex > toIndex) condition
 769      */
 770     private static String outOfBoundsMsg(int fromIndex, int toIndex) {
 771         return "From Index: " + fromIndex + " > To Index: " + toIndex;
 772     }
 773 
 774     /**
 775      * Removes from this list all of its elements that are contained in the
 776      * specified collection.
 777      *
 778      * @param c collection containing elements to be removed from this list
 779      * @return {@code true} if this list changed as a result of the call
 780      * @throws ClassCastException if the class of an element of this list
 781      *         is incompatible with the specified collection
 782      * (<a href="Collection.html#optional-restrictions">optional</a>)
 783      * @throws NullPointerException if this list contains a null element and the
 784      *         specified collection does not permit null elements
 785      * (<a href="Collection.html#optional-restrictions">optional</a>),
 786      *         or if the specified collection is null
 787      * @see Collection#contains(Object)
 788      */
 789     public boolean removeAll(Collection<?> c) {
 790         return batchRemove(c, false, 0, size);
 791     }
 792 
 793     /**
 794      * Retains only the elements in this list that are contained in the
 795      * specified collection.  In other words, removes from this list all
 796      * of its elements that are not contained in the specified collection.
 797      *
 798      * @param c collection containing elements to be retained in this list
 799      * @return {@code true} if this list changed as a result of the call
 800      * @throws ClassCastException if the class of an element of this list
 801      *         is incompatible with the specified collection
 802      * (<a href="Collection.html#optional-restrictions">optional</a>)
 803      * @throws NullPointerException if this list contains a null element and the
 804      *         specified collection does not permit null elements
 805      * (<a href="Collection.html#optional-restrictions">optional</a>),
 806      *         or if the specified collection is null
 807      * @see Collection#contains(Object)
 808      */
 809     public boolean retainAll(Collection<?> c) {
 810         return batchRemove(c, true, 0, size);
 811     }
 812 
 813     boolean batchRemove(Collection<?> c, boolean complement,
 814                         final int from, final int end) {
 815         Objects.requireNonNull(c);
 816         final Object[] es = elementData;
 817         int r;
 818         // Optimize for initial run of survivors
 819         for (r = from;; r++) {
 820             if (r == end)
 821                 return false;
 822             if (c.contains(es[r]) != complement)
 823                 break;
 824         }
 825         int w = r++;
 826         try {
 827             for (Object e; r < end; r++)
 828                 if (c.contains(e = es[r]) == complement)
 829                     es[w++] = e;
 830         } catch (Throwable ex) {
 831             // Preserve behavioral compatibility with AbstractCollection,
 832             // even if c.contains() throws.
 833             System.arraycopy(es, r, es, w, end - r);
 834             w += end - r;
 835             throw ex;
 836         } finally {
 837             modCount += end - w;
 838             shiftTailOverGap(es, w, end);
 839         }
 840         return true;
 841     }
 842 
 843     /**
 844      * Saves the state of the {@code ArrayList} instance to a stream
 845      * (that is, serializes it).
 846      *
 847      * @param s the stream
 848      * @throws java.io.IOException if an I/O error occurs
 849      * @serialData The length of the array backing the {@code ArrayList}
 850      *             instance is emitted (int), followed by all of its elements
 851      *             (each an {@code Object}) in the proper order.
 852      */
 853     @java.io.Serial
 854     private void writeObject(java.io.ObjectOutputStream s)
 855         throws java.io.IOException {
 856         // Write out element count, and any hidden stuff
 857         int expectedModCount = modCount;
 858         s.defaultWriteObject();
 859 
 860         // Write out size as capacity for behavioral compatibility with clone()
 861         s.writeInt(size);
 862 
 863         // Write out all elements in the proper order.
 864         for (int i=0; i<size; i++) {
 865             s.writeObject(elementData[i]);
 866         }
 867 
 868         if (modCount != expectedModCount) {
 869             throw new ConcurrentModificationException();
 870         }
 871     }
 872 
 873     /**
 874      * Reconstitutes the {@code ArrayList} instance from a stream (that is,
 875      * deserializes it).
 876      * @param s the stream
 877      * @throws ClassNotFoundException if the class of a serialized object
 878      *         could not be found
 879      * @throws java.io.IOException if an I/O error occurs
 880      */
 881     @java.io.Serial
 882     private void readObject(java.io.ObjectInputStream s)
 883         throws java.io.IOException, ClassNotFoundException {
 884 
 885         // Read in size, and any hidden stuff
 886         s.defaultReadObject();
 887 
 888         // Read in capacity
 889         s.readInt(); // ignored
 890 
 891         if (size > 0) {
 892             // like clone(), allocate array based upon size not capacity
 893             SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, size);
 894             Object[] elements = new Object[size];
 895 
 896             // Read in all elements in the proper order.
 897             for (int i = 0; i < size; i++) {
 898                 elements[i] = s.readObject();
 899             }
 900 
 901             elementData = elements;
 902         } else if (size == 0) {
 903             elementData = EMPTY_ELEMENTDATA;
 904         } else {
 905             throw new java.io.InvalidObjectException("Invalid size: " + size);
 906         }
 907     }
 908 
 909     /**
 910      * Returns a list iterator over the elements in this list (in proper
 911      * sequence), starting at the specified position in the list.
 912      * The specified index indicates the first element that would be
 913      * returned by an initial call to {@link ListIterator#next next}.
 914      * An initial call to {@link ListIterator#previous previous} would
 915      * return the element with the specified index minus one.
 916      *
 917      * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
 918      *
 919      * @throws IndexOutOfBoundsException {@inheritDoc}
 920      */
 921     public ListIterator<E> listIterator(int index) {
 922         rangeCheckForAdd(index);
 923         return new ListItr(index);
 924     }
 925 
 926     /**
 927      * Returns a list iterator over the elements in this list (in proper
 928      * sequence).
 929      *
 930      * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
 931      *
 932      * @see #listIterator(int)
 933      */
 934     public ListIterator<E> listIterator() {
 935         return new ListItr(0);
 936     }
 937 
 938     /**
 939      * Returns an iterator over the elements in this list in proper sequence.
 940      *
 941      * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
 942      *
 943      * @return an iterator over the elements in this list in proper sequence
 944      */
 945     public Iterator<E> iterator() {
 946         return new Itr();
 947     }
 948 
 949     /**
 950      * An optimized version of AbstractList.Itr
 951      */
 952     private class Itr implements Iterator<E> {
 953         int cursor;       // index of next element to return
 954         int lastRet = -1; // index of last element returned; -1 if no such
 955         int expectedModCount = modCount;
 956 
 957         // prevent creating a synthetic constructor
 958         Itr() {}
 959 
 960         public boolean hasNext() {
 961             return cursor != size;
 962         }
 963 
 964         @SuppressWarnings("unchecked")
 965         public E next() {
 966             checkForComodification();
 967             int i = cursor;
 968             if (i >= size)
 969                 throw new NoSuchElementException();
 970             Object[] elementData = ArrayList.this.elementData;
 971             if (i >= elementData.length)
 972                 throw new ConcurrentModificationException();
 973             cursor = i + 1;
 974             return (E) elementData[lastRet = i];
 975         }
 976 
 977         public void remove() {
 978             if (lastRet < 0)
 979                 throw new IllegalStateException();
 980             checkForComodification();
 981 
 982             try {
 983                 ArrayList.this.remove(lastRet);
 984                 cursor = lastRet;
 985                 lastRet = -1;
 986                 expectedModCount = modCount;
 987             } catch (IndexOutOfBoundsException ex) {
 988                 throw new ConcurrentModificationException();
 989             }
 990         }
 991 
 992         @Override
 993         public void forEachRemaining(Consumer<? super E> action) {
 994             Objects.requireNonNull(action);
 995             final int size = ArrayList.this.size;
 996             int i = cursor;
 997             if (i < size) {
 998                 final Object[] es = elementData;
 999                 if (i >= es.length)
1000                     throw new ConcurrentModificationException();
1001                 for (; i < size && modCount == expectedModCount; i++)
1002                     action.accept(elementAt(es, i));
1003                 // update once at end to reduce heap write traffic
1004                 cursor = i;
1005                 lastRet = i - 1;
1006                 checkForComodification();
1007             }
1008         }
1009 
1010         final void checkForComodification() {
1011             if (modCount != expectedModCount)
1012                 throw new ConcurrentModificationException();
1013         }
1014     }
1015 
1016     /**
1017      * An optimized version of AbstractList.ListItr
1018      */
1019     private class ListItr extends Itr implements ListIterator<E> {
1020         ListItr(int index) {
1021             super();
1022             cursor = index;
1023         }
1024 
1025         public boolean hasPrevious() {
1026             return cursor != 0;
1027         }
1028 
1029         public int nextIndex() {
1030             return cursor;
1031         }
1032 
1033         public int previousIndex() {
1034             return cursor - 1;
1035         }
1036 
1037         @SuppressWarnings("unchecked")
1038         public E previous() {
1039             checkForComodification();
1040             int i = cursor - 1;
1041             if (i < 0)
1042                 throw new NoSuchElementException();
1043             Object[] elementData = ArrayList.this.elementData;
1044             if (i >= elementData.length)
1045                 throw new ConcurrentModificationException();
1046             cursor = i;
1047             return (E) elementData[lastRet = i];
1048         }
1049 
1050         public void set(E e) {
1051             if (lastRet < 0)
1052                 throw new IllegalStateException();
1053             checkForComodification();
1054 
1055             try {
1056                 ArrayList.this.set(lastRet, e);
1057             } catch (IndexOutOfBoundsException ex) {
1058                 throw new ConcurrentModificationException();
1059             }
1060         }
1061 
1062         public void add(E e) {
1063             checkForComodification();
1064 
1065             try {
1066                 int i = cursor;
1067                 ArrayList.this.add(i, e);
1068                 cursor = i + 1;
1069                 lastRet = -1;
1070                 expectedModCount = modCount;
1071             } catch (IndexOutOfBoundsException ex) {
1072                 throw new ConcurrentModificationException();
1073             }
1074         }
1075     }
1076 
1077     /**
1078      * Returns a view of the portion of this list between the specified
1079      * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.  (If
1080      * {@code fromIndex} and {@code toIndex} are equal, the returned list is
1081      * empty.)  The returned list is backed by this list, so non-structural
1082      * changes in the returned list are reflected in this list, and vice-versa.
1083      * The returned list supports all of the optional list operations.
1084      *
1085      * <p>This method eliminates the need for explicit range operations (of
1086      * the sort that commonly exist for arrays).  Any operation that expects
1087      * a list can be used as a range operation by passing a subList view
1088      * instead of a whole list.  For example, the following idiom
1089      * removes a range of elements from a list:
1090      * <pre>
1091      *      list.subList(from, to).clear();
1092      * </pre>
1093      * Similar idioms may be constructed for {@link #indexOf(Object)} and
1094      * {@link #lastIndexOf(Object)}, and all of the algorithms in the
1095      * {@link Collections} class can be applied to a subList.
1096      *
1097      * <p>The semantics of the list returned by this method become undefined if
1098      * the backing list (i.e., this list) is <i>structurally modified</i> in
1099      * any way other than via the returned list.  (Structural modifications are
1100      * those that change the size of this list, or otherwise perturb it in such
1101      * a fashion that iterations in progress may yield incorrect results.)
1102      *
1103      * @throws IndexOutOfBoundsException {@inheritDoc}
1104      * @throws IllegalArgumentException {@inheritDoc}
1105      */
1106     public List<E> subList(int fromIndex, int toIndex) {
1107         subListRangeCheck(fromIndex, toIndex, size);
1108         return new SubList<>(this, fromIndex, toIndex);
1109     }
1110 
1111     private static class SubList<E> extends AbstractList<E> implements RandomAccess {
1112         private final ArrayList<E> root;
1113         private final SubList<E> parent;
1114         private final int offset;
1115         private int size;
1116 
1117         /**
1118          * Constructs a sublist of an arbitrary ArrayList.
1119          */
1120         public SubList(ArrayList<E> root, int fromIndex, int toIndex) {
1121             this.root = root;
1122             this.parent = null;
1123             this.offset = fromIndex;
1124             this.size = toIndex - fromIndex;
1125             this.modCount = root.modCount;
1126         }
1127 
1128         /**
1129          * Constructs a sublist of another SubList.
1130          */
1131         private SubList(SubList<E> parent, int fromIndex, int toIndex) {
1132             this.root = parent.root;
1133             this.parent = parent;
1134             this.offset = parent.offset + fromIndex;
1135             this.size = toIndex - fromIndex;
1136             this.modCount = root.modCount;
1137         }
1138 
1139         public E set(int index, E element) {
1140             Objects.checkIndex(index, size);
1141             checkForComodification();
1142             E oldValue = root.elementData(offset + index);
1143             root.elementData[offset + index] = element;
1144             return oldValue;
1145         }
1146 
1147         public E get(int index) {
1148             Objects.checkIndex(index, size);
1149             checkForComodification();
1150             return root.elementData(offset + index);
1151         }
1152 
1153         public int size() {
1154             checkForComodification();
1155             return size;
1156         }
1157 
1158         public void add(int index, E element) {
1159             rangeCheckForAdd(index);
1160             checkForComodification();
1161             root.add(offset + index, element);
1162             updateSizeAndModCount(1);
1163         }
1164 
1165         public E remove(int index) {
1166             Objects.checkIndex(index, size);
1167             checkForComodification();
1168             E result = root.remove(offset + index);
1169             updateSizeAndModCount(-1);
1170             return result;
1171         }
1172 
1173         protected void removeRange(int fromIndex, int toIndex) {
1174             checkForComodification();
1175             root.removeRange(offset + fromIndex, offset + toIndex);
1176             updateSizeAndModCount(fromIndex - toIndex);
1177         }
1178 
1179         public boolean addAll(Collection<? extends E> c) {
1180             return addAll(this.size, c);
1181         }
1182 
1183         public boolean addAll(int index, Collection<? extends E> c) {
1184             rangeCheckForAdd(index);
1185             int cSize = c.size();
1186             if (cSize==0)
1187                 return false;
1188             checkForComodification();
1189             root.addAll(offset + index, c);
1190             updateSizeAndModCount(cSize);
1191             return true;
1192         }
1193 
1194         public void replaceAll(UnaryOperator<E> operator) {
1195             root.replaceAllRange(operator, offset, offset + size);
1196         }
1197 
1198         public boolean removeAll(Collection<?> c) {
1199             return batchRemove(c, false);
1200         }
1201 
1202         public boolean retainAll(Collection<?> c) {
1203             return batchRemove(c, true);
1204         }
1205 
1206         private boolean batchRemove(Collection<?> c, boolean complement) {
1207             checkForComodification();
1208             int oldSize = root.size;
1209             boolean modified =
1210                 root.batchRemove(c, complement, offset, offset + size);
1211             if (modified)
1212                 updateSizeAndModCount(root.size - oldSize);
1213             return modified;
1214         }
1215 
1216         public boolean removeIf(Predicate<? super E> filter) {
1217             checkForComodification();
1218             int oldSize = root.size;
1219             boolean modified = root.removeIf(filter, offset, offset + size);
1220             if (modified)
1221                 updateSizeAndModCount(root.size - oldSize);
1222             return modified;
1223         }
1224 
1225         public Object[] toArray() {
1226             checkForComodification();
1227             return Arrays.copyOfRange(root.elementData, offset, offset + size);
1228         }
1229 
1230         @SuppressWarnings("unchecked")
1231         public <T> T[] toArray(T[] a) {
1232             checkForComodification();
1233             if (a.length < size)
1234                 return (T[]) Arrays.copyOfRange(
1235                         root.elementData, offset, offset + size, a.getClass());
1236             System.arraycopy(root.elementData, offset, a, 0, size);
1237             if (a.length > size)
1238                 a[size] = null;
1239             return a;
1240         }
1241 
1242         public boolean equals(Object o) {
1243             if (o == this) {
1244                 return true;
1245             }
1246 
1247             if (!(o instanceof List)) {
1248                 return false;
1249             }
1250 
1251             boolean equal = root.equalsRange((List<?>)o, offset, offset + size);
1252             checkForComodification();
1253             return equal;
1254         }
1255 
1256         public int hashCode() {
1257             int hash = root.hashCodeRange(offset, offset + size);
1258             checkForComodification();
1259             return hash;
1260         }
1261 
1262         public int indexOf(Object o) {
1263             int index = root.indexOfRange(o, offset, offset + size);
1264             checkForComodification();
1265             return index >= 0 ? index - offset : -1;
1266         }
1267 
1268         public int lastIndexOf(Object o) {
1269             int index = root.lastIndexOfRange(o, offset, offset + size);
1270             checkForComodification();
1271             return index >= 0 ? index - offset : -1;
1272         }
1273 
1274         public boolean contains(Object o) {
1275             return indexOf(o) >= 0;
1276         }
1277 
1278         public Iterator<E> iterator() {
1279             return listIterator();
1280         }
1281 
1282         public ListIterator<E> listIterator(int index) {
1283             checkForComodification();
1284             rangeCheckForAdd(index);
1285 
1286             return new ListIterator<E>() {
1287                 int cursor = index;
1288                 int lastRet = -1;
1289                 int expectedModCount = root.modCount;
1290 
1291                 public boolean hasNext() {
1292                     return cursor != SubList.this.size;
1293                 }
1294 
1295                 @SuppressWarnings("unchecked")
1296                 public E next() {
1297                     checkForComodification();
1298                     int i = cursor;
1299                     if (i >= SubList.this.size)
1300                         throw new NoSuchElementException();
1301                     Object[] elementData = root.elementData;
1302                     if (offset + i >= elementData.length)
1303                         throw new ConcurrentModificationException();
1304                     cursor = i + 1;
1305                     return (E) elementData[offset + (lastRet = i)];
1306                 }
1307 
1308                 public boolean hasPrevious() {
1309                     return cursor != 0;
1310                 }
1311 
1312                 @SuppressWarnings("unchecked")
1313                 public E previous() {
1314                     checkForComodification();
1315                     int i = cursor - 1;
1316                     if (i < 0)
1317                         throw new NoSuchElementException();
1318                     Object[] elementData = root.elementData;
1319                     if (offset + i >= elementData.length)
1320                         throw new ConcurrentModificationException();
1321                     cursor = i;
1322                     return (E) elementData[offset + (lastRet = i)];
1323                 }
1324 
1325                 public void forEachRemaining(Consumer<? super E> action) {
1326                     Objects.requireNonNull(action);
1327                     final int size = SubList.this.size;
1328                     int i = cursor;
1329                     if (i < size) {
1330                         final Object[] es = root.elementData;
1331                         if (offset + i >= es.length)
1332                             throw new ConcurrentModificationException();
1333                         for (; i < size && modCount == expectedModCount; i++)
1334                             action.accept(elementAt(es, offset + i));
1335                         // update once at end to reduce heap write traffic
1336                         cursor = i;
1337                         lastRet = i - 1;
1338                         checkForComodification();
1339                     }
1340                 }
1341 
1342                 public int nextIndex() {
1343                     return cursor;
1344                 }
1345 
1346                 public int previousIndex() {
1347                     return cursor - 1;
1348                 }
1349 
1350                 public void remove() {
1351                     if (lastRet < 0)
1352                         throw new IllegalStateException();
1353                     checkForComodification();
1354 
1355                     try {
1356                         SubList.this.remove(lastRet);
1357                         cursor = lastRet;
1358                         lastRet = -1;
1359                         expectedModCount = root.modCount;
1360                     } catch (IndexOutOfBoundsException ex) {
1361                         throw new ConcurrentModificationException();
1362                     }
1363                 }
1364 
1365                 public void set(E e) {
1366                     if (lastRet < 0)
1367                         throw new IllegalStateException();
1368                     checkForComodification();
1369 
1370                     try {
1371                         root.set(offset + lastRet, e);
1372                     } catch (IndexOutOfBoundsException ex) {
1373                         throw new ConcurrentModificationException();
1374                     }
1375                 }
1376 
1377                 public void add(E e) {
1378                     checkForComodification();
1379 
1380                     try {
1381                         int i = cursor;
1382                         SubList.this.add(i, e);
1383                         cursor = i + 1;
1384                         lastRet = -1;
1385                         expectedModCount = root.modCount;
1386                     } catch (IndexOutOfBoundsException ex) {
1387                         throw new ConcurrentModificationException();
1388                     }
1389                 }
1390 
1391                 final void checkForComodification() {
1392                     if (root.modCount != expectedModCount)
1393                         throw new ConcurrentModificationException();
1394                 }
1395             };
1396         }
1397 
1398         public List<E> subList(int fromIndex, int toIndex) {
1399             subListRangeCheck(fromIndex, toIndex, size);
1400             return new SubList<>(this, fromIndex, toIndex);
1401         }
1402 
1403         private void rangeCheckForAdd(int index) {
1404             if (index < 0 || index > this.size)
1405                 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
1406         }
1407 
1408         private String outOfBoundsMsg(int index) {
1409             return "Index: "+index+", Size: "+this.size;
1410         }
1411 
1412         private void checkForComodification() {
1413             if (root.modCount != modCount)
1414                 throw new ConcurrentModificationException();
1415         }
1416 
1417         private void updateSizeAndModCount(int sizeChange) {
1418             SubList<E> slist = this;
1419             do {
1420                 slist.size += sizeChange;
1421                 slist.modCount = root.modCount;
1422                 slist = slist.parent;
1423             } while (slist != null);
1424         }
1425 
1426         public Spliterator<E> spliterator() {
1427             checkForComodification();
1428 
1429             // ArrayListSpliterator not used here due to late-binding
1430             return new Spliterator<E>() {
1431                 private int index = offset; // current index, modified on advance/split
1432                 private int fence = -1; // -1 until used; then one past last index
1433                 private int expectedModCount; // initialized when fence set
1434 
1435                 private int getFence() { // initialize fence to size on first use
1436                     int hi; // (a specialized variant appears in method forEach)
1437                     if ((hi = fence) < 0) {
1438                         expectedModCount = modCount;
1439                         hi = fence = offset + size;
1440                     }
1441                     return hi;
1442                 }
1443 
1444                 public ArrayList<E>.ArrayListSpliterator trySplit() {
1445                     int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
1446                     // ArrayListSpliterator can be used here as the source is already bound
1447                     return (lo >= mid) ? null : // divide range in half unless too small
1448                         root.new ArrayListSpliterator(lo, index = mid, expectedModCount);
1449                 }
1450 
1451                 public boolean tryAdvance(Consumer<? super E> action) {
1452                     Objects.requireNonNull(action);
1453                     int hi = getFence(), i = index;
1454                     if (i < hi) {
1455                         index = i + 1;
1456                         @SuppressWarnings("unchecked") E e = (E)root.elementData[i];
1457                         action.accept(e);
1458                         if (root.modCount != expectedModCount)
1459                             throw new ConcurrentModificationException();
1460                         return true;
1461                     }
1462                     return false;
1463                 }
1464 
1465                 public void forEachRemaining(Consumer<? super E> action) {
1466                     Objects.requireNonNull(action);
1467                     int i, hi, mc; // hoist accesses and checks from loop
1468                     ArrayList<E> lst = root;
1469                     Object[] a;
1470                     if ((a = lst.elementData) != null) {
1471                         if ((hi = fence) < 0) {
1472                             mc = modCount;
1473                             hi = offset + size;
1474                         }
1475                         else
1476                             mc = expectedModCount;
1477                         if ((i = index) >= 0 && (index = hi) <= a.length) {
1478                             for (; i < hi; ++i) {
1479                                 @SuppressWarnings("unchecked") E e = (E) a[i];
1480                                 action.accept(e);
1481                             }
1482                             if (lst.modCount == mc)
1483                                 return;
1484                         }
1485                     }
1486                     throw new ConcurrentModificationException();
1487                 }
1488 
1489                 public long estimateSize() {
1490                     return getFence() - index;
1491                 }
1492 
1493                 public int characteristics() {
1494                     return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
1495                 }
1496             };
1497         }
1498     }
1499 
1500     /**
1501      * @throws NullPointerException {@inheritDoc}
1502      */
1503     @Override
1504     public void forEach(Consumer<? super E> action) {
1505         Objects.requireNonNull(action);
1506         final int expectedModCount = modCount;
1507         final Object[] es = elementData;
1508         final int size = this.size;
1509         for (int i = 0; modCount == expectedModCount && i < size; i++)
1510             action.accept(elementAt(es, i));
1511         if (modCount != expectedModCount)
1512             throw new ConcurrentModificationException();
1513     }
1514 
1515     /**
1516      * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
1517      * and <em>fail-fast</em> {@link Spliterator} over the elements in this
1518      * list.
1519      *
1520      * <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
1521      * {@link Spliterator#SUBSIZED}, and {@link Spliterator#ORDERED}.
1522      * Overriding implementations should document the reporting of additional
1523      * characteristic values.
1524      *
1525      * @return a {@code Spliterator} over the elements in this list
1526      * @since 1.8
1527      */
1528     @Override
1529     public Spliterator<E> spliterator() {
1530         return new ArrayListSpliterator(0, -1, 0);
1531     }
1532 
1533     /** Index-based split-by-two, lazily initialized Spliterator */
1534     final class ArrayListSpliterator implements Spliterator<E> {
1535 
1536         /*
1537          * If ArrayLists were immutable, or structurally immutable (no
1538          * adds, removes, etc), we could implement their spliterators
1539          * with Arrays.spliterator. Instead we detect as much
1540          * interference during traversal as practical without
1541          * sacrificing much performance. We rely primarily on
1542          * modCounts. These are not guaranteed to detect concurrency
1543          * violations, and are sometimes overly conservative about
1544          * within-thread interference, but detect enough problems to
1545          * be worthwhile in practice. To carry this out, we (1) lazily
1546          * initialize fence and expectedModCount until the latest
1547          * point that we need to commit to the state we are checking
1548          * against; thus improving precision.  (This doesn't apply to
1549          * SubLists, that create spliterators with current non-lazy
1550          * values).  (2) We perform only a single
1551          * ConcurrentModificationException check at the end of forEach
1552          * (the most performance-sensitive method). When using forEach
1553          * (as opposed to iterators), we can normally only detect
1554          * interference after actions, not before. Further
1555          * CME-triggering checks apply to all other possible
1556          * violations of assumptions for example null or too-small
1557          * elementData array given its size(), that could only have
1558          * occurred due to interference.  This allows the inner loop
1559          * of forEach to run without any further checks, and
1560          * simplifies lambda-resolution. While this does entail a
1561          * number of checks, note that in the common case of
1562          * list.stream().forEach(a), no checks or other computation
1563          * occur anywhere other than inside forEach itself.  The other
1564          * less-often-used methods cannot take advantage of most of
1565          * these streamlinings.
1566          */
1567 
1568         private int index; // current index, modified on advance/split
1569         private int fence; // -1 until used; then one past last index
1570         private int expectedModCount; // initialized when fence set
1571 
1572         /** Creates new spliterator covering the given range. */
1573         ArrayListSpliterator(int origin, int fence, int expectedModCount) {
1574             this.index = origin;
1575             this.fence = fence;
1576             this.expectedModCount = expectedModCount;
1577         }
1578 
1579         private int getFence() { // initialize fence to size on first use
1580             int hi; // (a specialized variant appears in method forEach)
1581             if ((hi = fence) < 0) {
1582                 expectedModCount = modCount;
1583                 hi = fence = size;
1584             }
1585             return hi;
1586         }
1587 
1588         public ArrayListSpliterator trySplit() {
1589             int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
1590             return (lo >= mid) ? null : // divide range in half unless too small
1591                 new ArrayListSpliterator(lo, index = mid, expectedModCount);
1592         }
1593 
1594         public boolean tryAdvance(Consumer<? super E> action) {
1595             if (action == null)
1596                 throw new NullPointerException();
1597             int hi = getFence(), i = index;
1598             if (i < hi) {
1599                 index = i + 1;
1600                 @SuppressWarnings("unchecked") E e = (E)elementData[i];
1601                 action.accept(e);
1602                 if (modCount != expectedModCount)
1603                     throw new ConcurrentModificationException();
1604                 return true;
1605             }
1606             return false;
1607         }
1608 
1609         public void forEachRemaining(Consumer<? super E> action) {
1610             int i, hi, mc; // hoist accesses and checks from loop
1611             Object[] a;
1612             if (action == null)
1613                 throw new NullPointerException();
1614             if ((a = elementData) != null) {
1615                 if ((hi = fence) < 0) {
1616                     mc = modCount;
1617                     hi = size;
1618                 }
1619                 else
1620                     mc = expectedModCount;
1621                 if ((i = index) >= 0 && (index = hi) <= a.length) {
1622                     for (; i < hi; ++i) {
1623                         @SuppressWarnings("unchecked") E e = (E) a[i];
1624                         action.accept(e);
1625                     }
1626                     if (modCount == mc)
1627                         return;
1628                 }
1629             }
1630             throw new ConcurrentModificationException();
1631         }
1632 
1633         public long estimateSize() {
1634             return getFence() - index;
1635         }
1636 
1637         public int characteristics() {
1638             return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
1639         }
1640     }
1641 
1642     // A tiny bit set implementation
1643 
1644     private static long[] nBits(int n) {
1645         return new long[((n - 1) >> 6) + 1];
1646     }
1647     private static void setBit(long[] bits, int i) {
1648         bits[i >> 6] |= 1L << i;
1649     }
1650     private static boolean isClear(long[] bits, int i) {
1651         return (bits[i >> 6] & (1L << i)) == 0;
1652     }
1653 
1654     /**
1655      * @throws NullPointerException {@inheritDoc}
1656      */
1657     @Override
1658     public boolean removeIf(Predicate<? super E> filter) {
1659         return removeIf(filter, 0, size);
1660     }
1661 
1662     /**
1663      * Removes all elements satisfying the given predicate, from index
1664      * i (inclusive) to index end (exclusive).
1665      */
1666     boolean removeIf(Predicate<? super E> filter, int i, final int end) {
1667         Objects.requireNonNull(filter);
1668         int expectedModCount = modCount;
1669         final Object[] es = elementData;
1670         // Optimize for initial run of survivors
1671         for (; i < end && !filter.test(elementAt(es, i)); i++)
1672             ;
1673         // Tolerate predicates that reentrantly access the collection for
1674         // read (but writers still get CME), so traverse once to find
1675         // elements to delete, a second pass to physically expunge.
1676         if (i < end) {
1677             final int beg = i;
1678             final long[] deathRow = nBits(end - beg);
1679             deathRow[0] = 1L;   // set bit 0
1680             for (i = beg + 1; i < end; i++)
1681                 if (filter.test(elementAt(es, i)))
1682                     setBit(deathRow, i - beg);
1683             if (modCount != expectedModCount)
1684                 throw new ConcurrentModificationException();
1685             modCount++;
1686             int w = beg;
1687             for (i = beg; i < end; i++)
1688                 if (isClear(deathRow, i - beg))
1689                     es[w++] = es[i];
1690             shiftTailOverGap(es, w, end);
1691             return true;
1692         } else {
1693             if (modCount != expectedModCount)
1694                 throw new ConcurrentModificationException();
1695             return false;
1696         }
1697     }
1698 
1699     @Override
1700     public void replaceAll(UnaryOperator<E> operator) {
1701         replaceAllRange(operator, 0, size);
1702         // TODO(8203662): remove increment of modCount from ...
1703         modCount++;
1704     }
1705 
1706     private void replaceAllRange(UnaryOperator<E> operator, int i, int end) {
1707         Objects.requireNonNull(operator);
1708         final int expectedModCount = modCount;
1709         final Object[] es = elementData;
1710         for (; modCount == expectedModCount && i < end; i++)
1711             es[i] = operator.apply(elementAt(es, i));
1712         if (modCount != expectedModCount)
1713             throw new ConcurrentModificationException();
1714     }
1715 
1716     @Override
1717     @SuppressWarnings("unchecked")
1718     public void sort(Comparator<? super E> c) {
1719         final int expectedModCount = modCount;
1720         Arrays.sort((E[]) elementData, 0, size, c);
1721         if (modCount != expectedModCount)
1722             throw new ConcurrentModificationException();
1723         modCount++;
1724     }
1725 
1726     void checkInvariants() {
1727         // assert size >= 0;
1728         // assert size == elementData.length || elementData[size] == null;
1729     }
1730 }