/* * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/** * Resizable-array implementation of the {@code List} interface. Implements * all optional list operations, and permits all elements, including * {@code null}. In addition to implementing the {@code List} interface, * this class provides methods to manipulate the size of the array that is * used internally to store the list. (This class is roughly equivalent to * {@code Vector}, except that it is unsynchronized.) * * <p>The {@code size}, {@code isEmpty}, {@code get}, {@code set}, * {@code iterator}, and {@code listIterator} operations run in constant * time. The {@code add} operation runs in <i>amortized constant time</i>, * that is, adding n elements requires O(n) time. All of the other operations * run in linear time (roughly speaking). The constant factor is low compared * to that for the {@code LinkedList} implementation. * * <p>Each {@code ArrayList} instance has a <i>capacity</i>. The capacity is * the size of the array used to store the elements in the list. It is always * at least as large as the list size. As elements are added to an ArrayList, * its capacity grows automatically. The details of the growth policy are not * specified beyond the fact that adding an element has constant amortized * time cost. * * <p>An application can increase the capacity of an {@code ArrayList} instance * before adding a large number of elements using the {@code ensureCapacity} * operation. This may reduce the amount of incremental reallocation. * * <p><strong>Note that this implementation is not synchronized.</strong> * If multiple threads access an {@code ArrayList} instance concurrently, * and at least one of the threads modifies the list structurally, it * <i>must</i> be synchronized externally. (A structural modification is * any operation that adds or deletes one or more elements, or explicitly * resizes the backing array; merely setting the value of an element is not * a structural modification.) This is typically accomplished by * synchronizing on some object that naturally encapsulates the list. * * If no such object exists, the list should be "wrapped" using the * {@link Collections#synchronizedList Collections.synchronizedList} * method. This is best done at creation time, to prevent accidental * unsynchronized access to the list:<pre> * List list = Collections.synchronizedList(new ArrayList(...));</pre> * * <p id="fail-fast"> * The iterators returned by this class's {@link #iterator() iterator} and * {@link #listIterator(int) listIterator} methods are <em>fail-fast</em>: * if the list is structurally modified at any time after the iterator is * created, in any way except through the iterator's own * {@link ListIterator#remove() remove} or * {@link ListIterator#add(Object) add} methods, the iterator will throw a * {@link ConcurrentModificationException}. Thus, in the face of * concurrent modification, the iterator fails quickly and cleanly, rather * than risking arbitrary, non-deterministic behavior at an undetermined * time in the future. * * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed * as it is, generally speaking, impossible to make any hard guarantees in the * presence of unsynchronized concurrent modification. Fail-fast iterators * throw {@code ConcurrentModificationException} on a best-effort basis. * Therefore, it would be wrong to write a program that depended on this * exception for its correctness: <i>the fail-fast behavior of iterators * should be used only to detect bugs.</i> * * <p>This class is a member of the * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework"> * Java Collections Framework</a>. * * @param <E> the type of elements in this list * * @author Josh Bloch * @author Neal Gafter * @see Collection * @see List * @see LinkedList * @see Vector * @since 1.2
*/ publicclass ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
@java.io.Serial privatestaticfinallong serialVersionUID = 8683452581122892189L;
/** * Shared empty array instance used for empty instances.
*/ privatestaticfinal Object[] EMPTY_ELEMENTDATA = {};
/** * Shared empty array instance used for default sized empty instances. We * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when * first element is added.
*/ privatestaticfinal Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * will be expanded to DEFAULT_CAPACITY when the first element is added.
*/ transient Object[] elementData; // non-private to simplify nested class access
/** * The size of the ArrayList (the number of elements it contains). * * @serial
*/ privateint size;
/** * Constructs an empty list with the specified initial capacity. * * @param initialCapacity the initial capacity of the list * @throws IllegalArgumentException if the specified initial capacity * is negative
*/ public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity];
} elseif (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA;
} else { thrownew IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/** * Constructs an empty list with an initial capacity of ten.
*/ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/** * Constructs a list containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * * @param c the collection whose elements are to be placed into this list * @throws NullPointerException if the specified collection is null
*/ public ArrayList(Collection<? extends E> c) {
Object[] a = c.toArray(); if ((size = a.length) != 0) { if (c.getClass() == ArrayList.class) {
elementData = a;
} else {
elementData = Arrays.copyOf(a, size, Object[].class);
}
} else { // replace with empty array.
elementData = EMPTY_ELEMENTDATA;
}
}
/** * Trims the capacity of this {@code ArrayList} instance to be the * list's current size. An application can use this operation to minimize * the storage of an {@code ArrayList} instance.
*/ publicvoid trimToSize() {
modCount++; if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
/** * Increases the capacity of this {@code ArrayList} instance, if * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity
*/ publicvoid ensureCapacity(int minCapacity) { if (minCapacity > elementData.length
&& !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
&& minCapacity <= DEFAULT_CAPACITY)) {
modCount++;
grow(minCapacity);
}
}
/** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity * @throws OutOfMemoryError if minCapacity is less than zero
*/ private Object[] grow(int minCapacity) { int oldCapacity = elementData.length; if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */); return elementData = Arrays.copyOf(elementData, newCapacity);
} else { return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
/** * Returns the number of elements in this list. * * @return the number of elements in this list
*/ publicint size() { return size;
}
/** * Returns {@code true} if this list contains no elements. * * @return {@code true} if this list contains no elements
*/ publicboolean isEmpty() { return size == 0;
}
/** * Returns {@code true} if this list contains the specified element. * More formally, returns {@code true} if and only if this list contains * at least one element {@code e} such that * {@code Objects.equals(o, e)}. * * @param o element whose presence in this list is to be tested * @return {@code true} if this list contains the specified element
*/ publicboolean contains(Object o) { return indexOf(o) >= 0;
}
/** * Returns the index of the first occurrence of the specified element * in this list, or -1 if this list does not contain the element. * More formally, returns the lowest index {@code i} such that * {@code Objects.equals(o, get(i))}, * or -1 if there is no such index.
*/ publicint indexOf(Object o) { return indexOfRange(o, 0, size);
}
int indexOfRange(Object o, int start, int end) {
Object[] es = elementData; if (o == null) { for (int i = start; i < end; i++) { if (es[i] == null) { return i;
}
}
} else { for (int i = start; i < end; i++) { if (o.equals(es[i])) { return i;
}
}
} return -1;
}
/** * Returns the index of the last occurrence of the specified element * in this list, or -1 if this list does not contain the element. * More formally, returns the highest index {@code i} such that * {@code Objects.equals(o, get(i))}, * or -1 if there is no such index.
*/ publicint lastIndexOf(Object o) { return lastIndexOfRange(o, 0, size);
}
int lastIndexOfRange(Object o, int start, int end) {
Object[] es = elementData; if (o == null) { for (int i = end - 1; i >= start; i--) { if (es[i] == null) { return i;
}
}
} else { for (int i = end - 1; i >= start; i--) { if (o.equals(es[i])) { return i;
}
}
} return -1;
}
/** * Returns a shallow copy of this {@code ArrayList} instance. (The * elements themselves are not copied.) * * @return a clone of this {@code ArrayList} instance
*/ public Object clone() { try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0; return v;
} catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable thrownew InternalError(e);
}
}
/** * Returns an array containing all of the elements in this list * in proper sequence (from first to last element). * * <p>The returned array will be "safe" in that no references to it are * maintained by this list. (In other words, this method must allocate * a new array). The caller is thus free to modify the returned array. * * <p>This method acts as bridge between array-based and collection-based * APIs. * * @return an array containing all of the elements in this list in * proper sequence
*/ public Object[] toArray() { return Arrays.copyOf(elementData, size);
}
/** * Returns an array containing all of the elements in this list in proper * sequence (from first to last element); the runtime type of the returned * array is that of the specified array. If the list fits in the * specified array, it is returned therein. Otherwise, a new array is * allocated with the runtime type of the specified array and the size of * this list. * * <p>If the list fits in the specified array with room to spare * (i.e., the array has more elements than the list), the element in * the array immediately following the end of the collection is set to * {@code null}. (This is useful in determining the length of the * list <i>only</i> if the caller knows that the list does not contain * any null elements.) * * @param a the array into which the elements of the list are to * be stored, if it is big enough; otherwise, a new array of the * same runtime type is allocated for this purpose. * @return an array containing the elements of the list * @throws ArrayStoreException if the runtime type of the specified array * is not a supertype of the runtime type of every element in * this list * @throws NullPointerException if the specified array is null
*/
@SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { if (a.length < size) // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size); if (a.length > size)
a[size] = null; return a;
}
// Positional Access Operations
@SuppressWarnings("unchecked")
E elementData(int index) { return (E) elementData[index];
}
@SuppressWarnings("unchecked") static <E> E elementAt(Object[] es, int index) { return (E) es[index];
}
/** * Returns the element at the specified position in this list. * * @param index index of the element to return * @return the element at the specified position in this list * @throws IndexOutOfBoundsException {@inheritDoc}
*/ public E get(int index) {
Objects.checkIndex(index, size); return elementData(index);
}
/** * Replaces the element at the specified position in this list with * the specified element. * * @param index index of the element to replace * @param element element to be stored at the specified position * @return the element previously at the specified position * @throws IndexOutOfBoundsException {@inheritDoc}
*/ public E set(int index, E element) {
Objects.checkIndex(index, size);
E oldValue = elementData(index);
elementData[index] = element; return oldValue;
}
/** * This helper method split out from add(E) to keep method * bytecode size under 35 (the -XX:MaxInlineSize default value), * which helps when add(E) is called in a C1-compiled loop.
*/ privatevoid add(E e, Object[] elementData, int s) { if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#add})
*/ publicboolean add(E e) {
modCount++;
add(e, elementData, size); returntrue;
}
/** * Inserts the specified element at the specified position in this * list. Shifts the element currently at that position (if any) and * any subsequent elements to the right (adds one to their indices). * * @param index index at which the specified element is to be inserted * @param element element to be inserted * @throws IndexOutOfBoundsException {@inheritDoc}
*/ publicvoid add(int index, E element) {
rangeCheckForAdd(index);
modCount++; finalint s;
Object[] elementData; if ((s = size) == (elementData = this.elementData).length)
elementData = grow();
System.arraycopy(elementData, index,
elementData, index + 1,
s - index);
elementData[index] = element;
size = s + 1;
}
/** * Removes the element at the specified position in this list. * Shifts any subsequent elements to the left (subtracts one from their * indices). * * @param index the index of the element to be removed * @return the element that was removed from the list * @throws IndexOutOfBoundsException {@inheritDoc}
*/ public E remove(int index) {
Objects.checkIndex(index, size); final Object[] es = elementData;
@SuppressWarnings("unchecked") E oldValue = (E) es[index];
fastRemove(es, index);
return oldValue;
}
/** * {@inheritDoc}
*/ publicboolean equals(Object o) { if (o == this) { returntrue;
}
if (!(o instanceof List)) { returnfalse;
}
finalint expectedModCount = modCount; // ArrayList can be subclassed and given arbitrary behavior, but we can // still deal with the common case where o is ArrayList precisely boolean equal = (o.getClass() == ArrayList.class)
? equalsArrayList((ArrayList<?>) o)
: equalsRange((List<?>) o, 0, size);
boolean equalsRange(List<?> other, int from, int to) { final Object[] es = elementData; if (to > es.length) { thrownew ConcurrentModificationException();
} var oit = other.iterator(); for (; from < to; from++) { if (!oit.hasNext() || !Objects.equals(es[from], oit.next())) { returnfalse;
}
} return !oit.hasNext();
}
privateboolean equalsArrayList(ArrayList<?> other) { finalint otherModCount = other.modCount; finalint s = size; boolean equal; if (equal = (s == other.size)) { final Object[] otherEs = other.elementData; final Object[] es = elementData; if (s > es.length || s > otherEs.length) { thrownew ConcurrentModificationException();
} for (int i = 0; i < s; i++) { if (!Objects.equals(es[i], otherEs[i])) {
equal = false; break;
}
}
}
other.checkForComodification(otherModCount); return equal;
}
/** * {@inheritDoc}
*/ publicint hashCode() { int expectedModCount = modCount; int hash = hashCodeRange(0, size);
checkForComodification(expectedModCount); return hash;
}
int hashCodeRange(int from, int to) { final Object[] es = elementData; if (to > es.length) { thrownew ConcurrentModificationException();
} int hashCode = 1; for (int i = from; i < to; i++) {
Object e = es[i];
hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
} return hashCode;
}
/** * Removes the first occurrence of the specified element from this list, * if it is present. If the list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index * {@code i} such that * {@code Objects.equals(o, get(i))} * (if such an element exists). Returns {@code true} if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). * * @param o element to be removed from this list, if present * @return {@code true} if this list contained the specified element
*/ publicboolean remove(Object o) { final Object[] es = elementData; finalint size = this.size; int i = 0;
found: { if (o == null) { for (; i < size; i++) if (es[i] == null) break found;
} else { for (; i < size; i++) if (o.equals(es[i])) break found;
} returnfalse;
}
fastRemove(es, i); returntrue;
}
/** * Private remove method that skips bounds checking and does not * return the value removed.
*/ privatevoid fastRemove(Object[] es, int i) {
modCount++; finalint newSize; if ((newSize = size - 1) > i)
System.arraycopy(es, i + 1, es, i, newSize - i);
es[size = newSize] = null;
}
/** * Removes all of the elements from this list. The list will * be empty after this call returns.
*/ publicvoid clear() {
modCount++; final Object[] es = elementData; for (int to = size, i = size = 0; i < to; i++)
es[i] = null;
}
/** * Appends all of the elements in the specified collection to the end of * this list, in the order that they are returned by the * specified collection's Iterator. The behavior of this operation is * undefined if the specified collection is modified while the operation * is in progress. (This implies that the behavior of this call is * undefined if the specified collection is this list, and this * list is nonempty.) * * @param c collection containing elements to be added to this list * @return {@code true} if this list changed as a result of the call * @throws NullPointerException if the specified collection is null
*/ publicboolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
modCount++; int numNew = a.length; if (numNew == 0) returnfalse;
Object[] elementData; finalint s; if (numNew > (elementData = this.elementData).length - (s = size))
elementData = grow(s + numNew);
System.arraycopy(a, 0, elementData, s, numNew);
size = s + numNew; returntrue;
}
/** * Inserts all of the elements in the specified collection into this * list, starting at the specified position. Shifts the element * currently at that position (if any) and any subsequent elements to * the right (increases their indices). The new elements will appear * in the list in the order that they are returned by the * specified collection's iterator. * * @param index index at which to insert the first element from the * specified collection * @param c collection containing elements to be added to this list * @return {@code true} if this list changed as a result of the call * @throws IndexOutOfBoundsException {@inheritDoc} * @throws NullPointerException if the specified collection is null
*/ publicboolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
Object[] a = c.toArray();
modCount++; int numNew = a.length; if (numNew == 0) returnfalse;
Object[] elementData; finalint s; if (numNew > (elementData = this.elementData).length - (s = size))
elementData = grow(s + numNew);
int numMoved = s - index; if (numMoved > 0)
System.arraycopy(elementData, index,
elementData, index + numNew,
numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size = s + numNew; returntrue;
}
/** * Removes from this list all of the elements whose index is between * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. * Shifts any succeeding elements to the left (reduces their index). * This call shortens the list by {@code (toIndex - fromIndex)} elements. * (If {@code toIndex==fromIndex}, this operation has no effect.) * * @throws IndexOutOfBoundsException if {@code fromIndex} or * {@code toIndex} is out of range * ({@code fromIndex < 0 || * toIndex > size() || * toIndex < fromIndex})
*/ protectedvoid removeRange(int fromIndex, int toIndex) { if (fromIndex > toIndex) { thrownew IndexOutOfBoundsException(
outOfBoundsMsg(fromIndex, toIndex));
}
modCount++;
shiftTailOverGap(elementData, fromIndex, toIndex);
}
/** Erases the gap from lo to hi, by sliding down following elements. */ privatevoid shiftTailOverGap(Object[] es, int lo, int hi) {
System.arraycopy(es, hi, es, lo, size - hi); for (int to = size, i = (size -= hi - lo); i < to; i++)
es[i] = null;
}
/** * A version of rangeCheck used by add and addAll.
*/ privatevoid rangeCheckForAdd(int index) { if (index > size || index < 0) thrownew IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/** * Constructs an IndexOutOfBoundsException detail message. * Of the many possible refactorings of the error handling code, * this "outlining" performs best with both server and client VMs.
*/ private String outOfBoundsMsg(int index) { return"Index: "+index+", Size: "+size;
}
/** * A version used in checking (fromIndex > toIndex) condition
*/ privatestatic String outOfBoundsMsg(int fromIndex, int toIndex) { return"From Index: " + fromIndex + " > To Index: " + toIndex;
}
/** * Removes from this list all of its elements that are contained in the * specified collection. * * @param c collection containing elements to be removed from this list * @return {@code true} if this list changed as a result of the call * @throws ClassCastException if the class of an element of this list * is incompatible with the specified collection * (<a href="Collection.html#optional-restrictions">optional</a>) * @throws NullPointerException if this list contains a null element and the * specified collection does not permit null elements * (<a href="Collection.html#optional-restrictions">optional</a>), * or if the specified collection is null * @see Collection#contains(Object)
*/ publicboolean removeAll(Collection<?> c) { return batchRemove(c, false, 0, size);
}
/** * Retains only the elements in this list that are contained in the * specified collection. In other words, removes from this list all * of its elements that are not contained in the specified collection. * * @param c collection containing elements to be retained in this list * @return {@code true} if this list changed as a result of the call * @throws ClassCastException if the class of an element of this list * is incompatible with the specified collection * (<a href="Collection.html#optional-restrictions">optional</a>) * @throws NullPointerException if this list contains a null element and the * specified collection does not permit null elements * (<a href="Collection.html#optional-restrictions">optional</a>), * or if the specified collection is null * @see Collection#contains(Object)
*/ publicboolean retainAll(Collection<?> c) { return batchRemove(c, true, 0, size);
}
boolean batchRemove(Collection<?> c, boolean complement, finalint from, finalint end) {
Objects.requireNonNull(c); final Object[] es = elementData; int r; // Optimize for initial run of survivors for (r = from;; r++) { if (r == end) returnfalse; if (c.contains(es[r]) != complement) break;
} int w = r++; try { for (Object e; r < end; r++) if (c.contains(e = es[r]) == complement)
es[w++] = e;
} catch (Throwable ex) { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws.
System.arraycopy(es, r, es, w, end - r);
w += end - r; throw ex;
} finally {
modCount += end - w;
shiftTailOverGap(es, w, end);
} returntrue;
}
/** * Saves the state of the {@code ArrayList} instance to a stream * (that is, serializes it). * * @param s the stream * @throws java.io.IOException if an I/O error occurs * @serialData The length of the array backing the {@code ArrayList} * instance is emitted (int), followed by all of its elements * (each an {@code Object}) in the proper order.
*/
@java.io.Serial privatevoid writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { // Write out element count, and any hidden stuff int expectedModCount = modCount;
s.defaultWriteObject();
// Write out size as capacity for behavioral compatibility with clone()
s.writeInt(size);
// Write out all elements in the proper order. for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) { thrownew ConcurrentModificationException();
}
}
/** * Reconstitutes the {@code ArrayList} instance from a stream (that is, * deserializes it). * @param s the stream * @throws ClassNotFoundException if the class of a serialized object * could not be found * @throws java.io.IOException if an I/O error occurs
*/
@java.io.Serial privatevoid readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
// Read in size, and any hidden stuff
s.defaultReadObject();
// Read in capacity
s.readInt(); // ignored
if (size > 0) { // like clone(), allocate array based upon size not capacity
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, size);
Object[] elements = new Object[size];
// Read in all elements in the proper order. for (int i = 0; i < size; i++) {
elements[i] = s.readObject();
}
/** * Returns a list iterator over the elements in this list (in proper * sequence), starting at the specified position in the list. * The specified index indicates the first element that would be * returned by an initial call to {@link ListIterator#next next}. * An initial call to {@link ListIterator#previous previous} would * return the element with the specified index minus one. * * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>. * * @throws IndexOutOfBoundsException {@inheritDoc}
*/ public ListIterator<E> listIterator(int index) {
rangeCheckForAdd(index); returnnew ListItr(index);
}
/** * Returns a list iterator over the elements in this list (in proper * sequence). * * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>. * * @see #listIterator(int)
*/ public ListIterator<E> listIterator() { returnnew ListItr(0);
}
/** * Returns an iterator over the elements in this list in proper sequence. * * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>. * * @return an iterator over the elements in this list in proper sequence
*/ public Iterator<E> iterator() { returnnew Itr();
}
/** * An optimized version of AbstractList.Itr
*/ privateclass Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount;
// prevent creating a synthetic constructor
Itr() {}
@SuppressWarnings("unchecked") public E next() {
checkForComodification(); int i = cursor; if (i >= size) thrownew NoSuchElementException();
Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) thrownew ConcurrentModificationException();
cursor = i + 1; return (E) elementData[lastRet = i];
}
publicvoid remove() { if (lastRet < 0) thrownew IllegalStateException();
checkForComodification();
@Override publicvoid forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action); finalint size = ArrayList.this.size; int i = cursor; if (i < size) { final Object[] es = elementData; if (i >= es.length) thrownew ConcurrentModificationException(); for (; i < size && modCount == expectedModCount; i++)
action.accept(elementAt(es, i)); // update once at end to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
}
@SuppressWarnings("unchecked") public E previous() {
checkForComodification(); int i = cursor - 1; if (i < 0) thrownew NoSuchElementException();
Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) thrownew ConcurrentModificationException();
cursor = i; return (E) elementData[lastRet = i];
}
try { int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) { thrownew ConcurrentModificationException();
}
}
}
/** * Returns a view of the portion of this list between the specified * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. (If * {@code fromIndex} and {@code toIndex} are equal, the returned list is * empty.) The returned list is backed by this list, so non-structural * changes in the returned list are reflected in this list, and vice-versa. * The returned list supports all of the optional list operations. * * <p>This method eliminates the need for explicit range operations (of * the sort that commonly exist for arrays). Any operation that expects * a list can be used as a range operation by passing a subList view * instead of a whole list. For example, the following idiom * removes a range of elements from a list: * <pre> * list.subList(from, to).clear(); * </pre> * Similar idioms may be constructed for {@link #indexOf(Object)} and * {@link #lastIndexOf(Object)}, and all of the algorithms in the * {@link Collections} class can be applied to a subList. * * <p>The semantics of the list returned by this method become undefined if * the backing list (i.e., this list) is <i>structurally modified</i> in * any way other than via the returned list. (Structural modifications are * those that change the size of this list, or otherwise perturb it in such * a fashion that iterations in progress may yield incorrect results.) * * @throws IndexOutOfBoundsException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc}
*/ public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size); returnnew SubList<>(this, fromIndex, toIndex);
}
public E remove(int index) {
Objects.checkIndex(index, size);
checkForComodification();
E result = root.remove(offset + index);
updateSizeAndModCount(-1); return result;
}
@SuppressWarnings("unchecked") public E next() {
checkForComodification(); int i = cursor; if (i >= SubList.this.size) thrownew NoSuchElementException();
Object[] elementData = root.elementData; if (offset + i >= elementData.length) thrownew ConcurrentModificationException();
cursor = i + 1; return (E) elementData[offset + (lastRet = i)];
}
@SuppressWarnings("unchecked") public E previous() {
checkForComodification(); int i = cursor - 1; if (i < 0) thrownew NoSuchElementException();
Object[] elementData = root.elementData; if (offset + i >= elementData.length) thrownew ConcurrentModificationException();
cursor = i; return (E) elementData[offset + (lastRet = i)];
}
publicvoid forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action); finalint size = SubList.this.size; int i = cursor; if (i < size) { final Object[] es = root.elementData; if (offset + i >= es.length) thrownew ConcurrentModificationException(); for (; i < size && root.modCount == expectedModCount; i++)
action.accept(elementAt(es, offset + i)); // update once at end to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
}
publicint nextIndex() { return cursor;
}
publicint previousIndex() { return cursor - 1;
}
publicvoid remove() { if (lastRet < 0) thrownew IllegalStateException();
checkForComodification();
public Spliterator<E> spliterator() {
checkForComodification();
// ArrayListSpliterator not used here due to late-binding returnnew Spliterator<E>() { privateint index = offset; // current index, modified on advance/split privateint fence = -1; // -1 until used; then one past last index privateint expectedModCount; // initialized when fence set
privateint getFence() { // initialize fence to size on first use int hi; // (a specialized variant appears in method forEach) if ((hi = fence) < 0) {
expectedModCount = modCount;
hi = fence = offset + size;
} return hi;
}
public ArrayList<E>.ArrayListSpliterator trySplit() { int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; // ArrayListSpliterator can be used here as the source is already bound return (lo >= mid) ? null : // divide range in half unless too small
root.new ArrayListSpliterator(lo, index = mid, expectedModCount);
}
publicboolean tryAdvance(Consumer<? super E> action) {
Objects.requireNonNull(action); int hi = getFence(), i = index; if (i < hi) {
index = i + 1;
@SuppressWarnings("unchecked") E e = (E)root.elementData[i];
action.accept(e); if (root.modCount != expectedModCount) thrownew ConcurrentModificationException(); returntrue;
} returnfalse;
}
publicvoid forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action); int i, hi, mc; // hoist accesses and checks from loop
ArrayList<E> lst = root;
Object[] a; if ((a = lst.elementData) != null) { if ((hi = fence) < 0) {
mc = modCount;
hi = offset + size;
} else
mc = expectedModCount; if ((i = index) >= 0 && (index = hi) <= a.length) { for (; i < hi; ++i) {
@SuppressWarnings("unchecked") E e = (E) a[i];
action.accept(e);
} if (lst.modCount == mc) return;
}
} thrownew ConcurrentModificationException();
}
/** * @throws NullPointerException {@inheritDoc}
*/
@Override publicvoid forEach(Consumer<? super E> action) {
Objects.requireNonNull(action); finalint expectedModCount = modCount; final Object[] es = elementData; finalint size = this.size; for (int i = 0; modCount == expectedModCount && i < size; i++)
action.accept(elementAt(es, i)); if (modCount != expectedModCount) thrownew ConcurrentModificationException();
}
/** * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em> * and <em>fail-fast</em> {@link Spliterator} over the elements in this * list. * * <p>The {@code Spliterator} reports {@link Spliterator#SIZED}, * {@link Spliterator#SUBSIZED}, and {@link Spliterator#ORDERED}. * Overriding implementations should document the reporting of additional * characteristic values. * * @return a {@code Spliterator} over the elements in this list * @since 1.8
*/
@Override public Spliterator<E> spliterator() { returnnew ArrayListSpliterator(0, -1, 0);
}
/* * If ArrayLists were immutable, or structurally immutable (no * adds, removes, etc), we could implement their spliterators * with Arrays.spliterator. Instead we detect as much * interference during traversal as practical without * sacrificing much performance. We rely primarily on * modCounts. These are not guaranteed to detect concurrency * violations, and are sometimes overly conservative about * within-thread interference, but detect enough problems to * be worthwhile in practice. To carry this out, we (1) lazily * initialize fence and expectedModCount until the latest * point that we need to commit to the state we are checking * against; thus improving precision. (This doesn't apply to * SubLists, that create spliterators with current non-lazy * values). (2) We perform only a single * ConcurrentModificationException check at the end of forEach * (the most performance-sensitive method). When using forEach * (as opposed to iterators), we can normally only detect * interference after actions, not before. Further * CME-triggering checks apply to all other possible * violations of assumptions for example null or too-small * elementData array given its size(), that could only have * occurred due to interference. This allows the inner loop * of forEach to run without any further checks, and * simplifies lambda-resolution. While this does entail a * number of checks, note that in the common case of * list.stream().forEach(a), no checks or other computation * occur anywhere other than inside forEach itself. The other * less-often-used methods cannot take advantage of most of * these streamlinings.
*/
privateint index; // current index, modified on advance/split privateint fence; // -1 until used; then one past last index privateint expectedModCount; // initialized when fence set
/** Creates new spliterator covering the given range. */
ArrayListSpliterator(int origin, int fence, int expectedModCount) { this.index = origin; this.fence = fence; this.expectedModCount = expectedModCount;
}
privateint getFence() { // initialize fence to size on first use int hi; // (a specialized variant appears in method forEach) if ((hi = fence) < 0) {
expectedModCount = modCount;
hi = fence = size;
} return hi;
}
public ArrayListSpliterator trySplit() { int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; return (lo >= mid) ? null : // divide range in half unless too small new ArrayListSpliterator(lo, index = mid, expectedModCount);
}
publicboolean tryAdvance(Consumer<? super E> action) { if (action == null) thrownew NullPointerException(); int hi = getFence(), i = index; if (i < hi) {
index = i + 1;
@SuppressWarnings("unchecked") E e = (E)elementData[i];
action.accept(e); if (modCount != expectedModCount) thrownew ConcurrentModificationException(); returntrue;
} returnfalse;
}
publicvoid forEachRemaining(Consumer<? super E> action) { int i, hi, mc; // hoist accesses and checks from loop
Object[] a; if (action == null) thrownew NullPointerException(); if ((a = elementData) != null) { if ((hi = fence) < 0) {
mc = modCount;
hi = size;
} else
mc = expectedModCount; if ((i = index) >= 0 && (index = hi) <= a.length) { for (; i < hi; ++i) {
@SuppressWarnings("unchecked") E e = (E) a[i];
action.accept(e);
} if (modCount == mc) return;
}
} thrownew ConcurrentModificationException();
}
/** * Removes all elements satisfying the given predicate, from index * i (inclusive) to index end (exclusive).
*/ boolean removeIf(Predicate<? super E> filter, int i, finalint end) {
Objects.requireNonNull(filter); int expectedModCount = modCount; final Object[] es = elementData; // Optimize for initial run of survivors for (; i < end && !filter.test(elementAt(es, i)); i++)
; // Tolerate predicates that reentrantly access the collection for // read (but writers still get CME), so traverse once to find // elements to delete, a second pass to physically expunge. if (i < end) { finalint beg = i; finallong[] deathRow = nBits(end - beg);
deathRow[0] = 1L; // set bit 0 for (i = beg + 1; i < end; i++) if (filter.test(elementAt(es, i)))
setBit(deathRow, i - beg); if (modCount != expectedModCount) thrownew ConcurrentModificationException();
modCount++; int w = beg; for (i = beg; i < end; i++) if (isClear(deathRow, i - beg))
es[w++] = es[i];
shiftTailOverGap(es, w, end); returntrue;
} else { if (modCount != expectedModCount) thrownew ConcurrentModificationException(); returnfalse;
}
}
@Override publicvoid replaceAll(UnaryOperator<E> operator) {
replaceAllRange(operator, 0, size); // TODO(8203662): remove increment of modCount from ...
modCount++;
}
privatevoid replaceAllRange(UnaryOperator<E> operator, int i, int end) {
Objects.requireNonNull(operator); finalint expectedModCount = modCount; final Object[] es = elementData; for (; modCount == expectedModCount && i < end; i++)
es[i] = operator.apply(elementAt(es, i)); if (modCount != expectedModCount) thrownew ConcurrentModificationException();
}
@Override
@SuppressWarnings("unchecked") publicvoid sort(Comparator<? super E> c) { finalint expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c); if (modCount != expectedModCount) thrownew ConcurrentModificationException();
modCount++;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.