--- old/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java 2018-04-10 11:23:26.727350287 -0700 +++ new/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java 2018-04-10 11:23:26.483350397 -0700 @@ -35,7 +35,6 @@ package java.util.concurrent; import java.lang.reflect.Field; -import java.util.AbstractList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; @@ -134,17 +133,17 @@ * @throws NullPointerException if the specified collection is null */ public CopyOnWriteArrayList(Collection c) { - Object[] elements; + Object[] es; if (c.getClass() == CopyOnWriteArrayList.class) - elements = ((CopyOnWriteArrayList)c).getArray(); + es = ((CopyOnWriteArrayList)c).getArray(); else { - elements = c.toArray(); + es = c.toArray(); // defend against c.toArray (incorrectly) not returning Object[] // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652) - if (elements.getClass() != Object[].class) - elements = Arrays.copyOf(elements, elements.length, Object[].class); + if (es.getClass() != Object[].class) + es = Arrays.copyOf(es, es.length, Object[].class); } - setArray(elements); + setArray(es); } /** @@ -180,20 +179,19 @@ * static version of indexOf, to allow repeated calls without * needing to re-acquire array each time. * @param o element to search for - * @param elements the array - * @param index first index to search - * @param fence one past last index to search + * @param es the array + * @param from first index to search + * @param to one past last index to search * @return index of element, or -1 if absent */ - private static int indexOf(Object o, Object[] elements, - int index, int fence) { + private static int indexOfRange(Object o, Object[] es, int from, int to) { if (o == null) { - for (int i = index; i < fence; i++) - if (elements[i] == null) + for (int i = from; i < to; i++) + if (es[i] == null) return i; } else { - for (int i = index; i < fence; i++) - if (o.equals(elements[i])) + for (int i = from; i < to; i++) + if (o.equals(es[i])) return i; } return -1; @@ -202,18 +200,19 @@ /** * static version of lastIndexOf. * @param o element to search for - * @param elements the array - * @param index first index to search + * @param es the array + * @param from index of first element of range, last element to search + * @param to one past last element of range, first element to search * @return index of element, or -1 if absent */ - private static int lastIndexOf(Object o, Object[] elements, int index) { + private static int lastIndexOfRange(Object o, Object[] es, int from, int to) { if (o == null) { - for (int i = index; i >= 0; i--) - if (elements[i] == null) + for (int i = to - 1; i >= from; i--) + if (es[i] == null) return i; } else { - for (int i = index; i >= 0; i--) - if (o.equals(elements[i])) + for (int i = to - 1; i >= from; i--) + if (o.equals(es[i])) return i; } return -1; @@ -228,16 +227,15 @@ * @return {@code true} if this list contains the specified element */ public boolean contains(Object o) { - Object[] elements = getArray(); - return indexOf(o, elements, 0, elements.length) >= 0; + return indexOf(o) >= 0; } /** * {@inheritDoc} */ public int indexOf(Object o) { - Object[] elements = getArray(); - return indexOf(o, elements, 0, elements.length); + Object[] es = getArray(); + return indexOfRange(o, es, 0, es.length); } /** @@ -256,16 +254,16 @@ * @throws IndexOutOfBoundsException if the specified index is negative */ public int indexOf(E e, int index) { - Object[] elements = getArray(); - return indexOf(e, elements, index, elements.length); + Object[] es = getArray(); + return indexOfRange(e, es, index, es.length); } /** * {@inheritDoc} */ public int lastIndexOf(Object o) { - Object[] elements = getArray(); - return lastIndexOf(o, elements, elements.length - 1); + Object[] es = getArray(); + return lastIndexOfRange(o, es, 0, es.length); } /** @@ -285,8 +283,8 @@ * than or equal to the current size of this list */ public int lastIndexOf(E e, int index) { - Object[] elements = getArray(); - return lastIndexOf(e, elements, index); + Object[] es = getArray(); + return lastIndexOfRange(e, es, 0, index + 1); } /** @@ -322,8 +320,7 @@ * @return an array containing all the elements in this list */ public Object[] toArray() { - Object[] elements = getArray(); - return Arrays.copyOf(elements, elements.length); + return getArray().clone(); } /** @@ -366,12 +363,12 @@ */ @SuppressWarnings("unchecked") public T[] toArray(T[] a) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; if (a.length < len) - return (T[]) Arrays.copyOf(elements, len, a.getClass()); + return (T[]) Arrays.copyOf(es, len, a.getClass()); else { - System.arraycopy(elements, 0, a, 0, len); + System.arraycopy(es, 0, a, 0, len); if (a.length > len) a[len] = null; return a; @@ -406,17 +403,13 @@ */ public E set(int index, E element) { synchronized (lock) { - Object[] elements = getArray(); - E oldValue = elementAt(elements, index); + Object[] es = getArray(); + E oldValue = elementAt(es, index); if (oldValue != element) { - int len = elements.length; - Object[] newElements = Arrays.copyOf(elements, len); - newElements[index] = element; - setArray(newElements); - } else { - // Not quite a no-op; ensures volatile write semantics - setArray(elements); + es = es.clone(); + es[index] = element; + setArray(es); } return oldValue; } @@ -430,11 +423,11 @@ */ public boolean add(E e) { synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; - Object[] newElements = Arrays.copyOf(elements, len + 1); - newElements[len] = e; - setArray(newElements); + Object[] es = getArray(); + int len = es.length; + es = Arrays.copyOf(es, len + 1); + es[len] = e; + setArray(es); return true; } } @@ -448,18 +441,18 @@ */ public void add(int index, E element) { synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; if (index > len || index < 0) throw new IndexOutOfBoundsException(outOfBounds(index, len)); Object[] newElements; int numMoved = len - index; if (numMoved == 0) - newElements = Arrays.copyOf(elements, len + 1); + newElements = Arrays.copyOf(es, len + 1); else { newElements = new Object[len + 1]; - System.arraycopy(elements, 0, newElements, 0, index); - System.arraycopy(elements, index, newElements, index + 1, + System.arraycopy(es, 0, newElements, 0, index); + System.arraycopy(es, index, newElements, index + 1, numMoved); } newElements[index] = element; @@ -476,19 +469,20 @@ */ public E remove(int index) { synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; - E oldValue = elementAt(elements, index); + Object[] es = getArray(); + int len = es.length; + E oldValue = elementAt(es, index); int numMoved = len - index - 1; + Object[] newElements; if (numMoved == 0) - setArray(Arrays.copyOf(elements, len - 1)); + newElements = Arrays.copyOf(es, len - 1); else { - Object[] newElements = new Object[len - 1]; - System.arraycopy(elements, 0, newElements, 0, index); - System.arraycopy(elements, index + 1, newElements, index, + newElements = new Object[len - 1]; + System.arraycopy(es, 0, newElements, 0, index); + System.arraycopy(es, index + 1, newElements, index, numMoved); - setArray(newElements); } + setArray(newElements); return oldValue; } } @@ -507,7 +501,7 @@ */ public boolean remove(Object o) { Object[] snapshot = getArray(); - int index = indexOf(o, snapshot, 0, snapshot.length); + int index = indexOfRange(o, snapshot, 0, snapshot.length); return index >= 0 && remove(o, snapshot, index); } @@ -532,7 +526,7 @@ return false; if (current[index] == o) break findIndex; - index = indexOf(o, current, index, len); + index = indexOfRange(o, current, index, len); if (index < 0) return false; } @@ -560,19 +554,19 @@ */ void removeRange(int fromIndex, int toIndex) { synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; if (fromIndex < 0 || toIndex > len || toIndex < fromIndex) throw new IndexOutOfBoundsException(); int newlen = len - (toIndex - fromIndex); int numMoved = len - toIndex; if (numMoved == 0) - setArray(Arrays.copyOf(elements, newlen)); + setArray(Arrays.copyOf(es, newlen)); else { Object[] newElements = new Object[newlen]; - System.arraycopy(elements, 0, newElements, 0, fromIndex); - System.arraycopy(elements, toIndex, newElements, + System.arraycopy(es, 0, newElements, 0, fromIndex); + System.arraycopy(es, toIndex, newElements, fromIndex, numMoved); setArray(newElements); } @@ -587,7 +581,7 @@ */ public boolean addIfAbsent(E e) { Object[] snapshot = getArray(); - return indexOf(e, snapshot, 0, snapshot.length) < 0 + return indexOfRange(e, snapshot, 0, snapshot.length) < 0 && addIfAbsent(e, snapshot); } @@ -606,7 +600,7 @@ if (current[i] != snapshot[i] && Objects.equals(e, current[i])) return false; - if (indexOf(e, current, common, len) >= 0) + if (indexOfRange(e, current, common, len) >= 0) return false; } Object[] newElements = Arrays.copyOf(current, len + 1); @@ -627,10 +621,10 @@ * @see #contains(Object) */ public boolean containsAll(Collection c) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; for (Object e : c) { - if (indexOf(e, elements, 0, len) < 0) + if (indexOfRange(e, es, 0, len) < 0) return false; } return true; @@ -694,18 +688,18 @@ if (cs.length == 0) return 0; synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; int added = 0; // uniquify and compact elements in cs for (int i = 0; i < cs.length; ++i) { Object e = cs[i]; - if (indexOf(e, elements, 0, len) < 0 && - indexOf(e, cs, 0, added) < 0) + if (indexOfRange(e, es, 0, len) < 0 && + indexOfRange(e, cs, 0, added) < 0) cs[added++] = e; } if (added > 0) { - Object[] newElements = Arrays.copyOf(elements, len + added); + Object[] newElements = Arrays.copyOf(es, len + added); System.arraycopy(cs, 0, newElements, len, added); setArray(newElements); } @@ -739,15 +733,16 @@ if (cs.length == 0) return false; synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; + Object[] newElements; if (len == 0 && cs.getClass() == Object[].class) - setArray(cs); + newElements = cs; else { - Object[] newElements = Arrays.copyOf(elements, len + cs.length); + newElements = Arrays.copyOf(es, len + cs.length); System.arraycopy(cs, 0, newElements, len, cs.length); - setArray(newElements); } + setArray(newElements); return true; } } @@ -771,8 +766,8 @@ public boolean addAll(int index, Collection c) { Object[] cs = c.toArray(); synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; if (index > len || index < 0) throw new IndexOutOfBoundsException(outOfBounds(index, len)); if (cs.length == 0) @@ -780,11 +775,11 @@ int numMoved = len - index; Object[] newElements; if (numMoved == 0) - newElements = Arrays.copyOf(elements, len + cs.length); + newElements = Arrays.copyOf(es, len + cs.length); else { newElements = new Object[len + cs.length]; - System.arraycopy(elements, 0, newElements, 0, index); - System.arraycopy(elements, index, + System.arraycopy(es, 0, newElements, 0, index); + System.arraycopy(es, index, newElements, index + cs.length, numMoved); } @@ -866,14 +861,14 @@ } public void replaceAll(UnaryOperator operator) { - Objects.requireNonNull(operator); synchronized (lock) { - replaceAll(operator, 0, getArray().length); + replaceAllRange(operator, 0, getArray().length); } } - void replaceAll(UnaryOperator operator, int i, int end) { + void replaceAllRange(UnaryOperator operator, int i, int end) { // assert Thread.holdsLock(lock); + Objects.requireNonNull(operator); final Object[] es = getArray().clone(); for (; i < end; i++) es[i] = operator.apply(elementAt(es, i)); @@ -882,12 +877,12 @@ public void sort(Comparator c) { synchronized (lock) { - sort(c, 0, getArray().length); + sortRange(c, 0, getArray().length); } } @SuppressWarnings("unchecked") - void sort(Comparator c, int i, int end) { + void sortRange(Comparator c, int i, int end) { // assert Thread.holdsLock(lock); final Object[] es = getArray().clone(); Arrays.sort(es, i, end, (Comparator)c); @@ -908,12 +903,12 @@ s.defaultWriteObject(); - Object[] elements = getArray(); + Object[] es = getArray(); // Write out array length - s.writeInt(elements.length); + s.writeInt(es.length); // Write out all elements in the proper order. - for (Object element : elements) + for (Object element : es) s.writeObject(element); } @@ -935,12 +930,12 @@ // Read in array length and allocate array int len = s.readInt(); SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, len); - Object[] elements = new Object[len]; + Object[] es = new Object[len]; // Read in all elements in the proper order. for (int i = 0; i < len; i++) - elements[i] = s.readObject(); - setArray(elements); + es[i] = s.readObject(); + setArray(es); } /** @@ -986,6 +981,15 @@ return !it.hasNext(); } + private static int hashCodeOfRange(Object[] es, int from, int to) { + int hashCode = 1; + for (int i = from; i < to; i++) { + Object x = es[i]; + hashCode = 31 * hashCode + (x == null ? 0 : x.hashCode()); + } + return hashCode; + } + /** * Returns the hash code value for this list. * @@ -994,10 +998,8 @@ * @return the hash code value for this list */ public int hashCode() { - int hashCode = 1; - for (Object x : getArray()) - hashCode = 31 * hashCode + (x == null ? 0 : x.hashCode()); - return hashCode; + Object[] es = getArray(); + return hashCodeOfRange(es, 0, es.length); } /** @@ -1037,12 +1039,12 @@ * @throws IndexOutOfBoundsException {@inheritDoc} */ public ListIterator listIterator(int index) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; if (index < 0 || index > len) throw new IndexOutOfBoundsException(outOfBounds(index, len)); - return new COWIterator(elements, index); + return new COWIterator(es, index); } /** @@ -1070,9 +1072,9 @@ /** Index of element to be returned by subsequent call to next. */ private int cursor; - COWIterator(Object[] elements, int initialCursor) { + COWIterator(Object[] es, int initialCursor) { cursor = initialCursor; - snapshot = elements; + snapshot = es; } public boolean hasNext() { @@ -1102,7 +1104,7 @@ } public int previousIndex() { - return cursor-1; + return cursor - 1; } /** @@ -1133,14 +1135,13 @@ } @Override - @SuppressWarnings("unchecked") public void forEachRemaining(Consumer action) { Objects.requireNonNull(action); final int size = snapshot.length; - for (int i = cursor; i < size; i++) { - action.accept((E) snapshot[i]); - } + int i = cursor; cursor = size; + for (; i < size; i++) + action.accept(elementAt(snapshot, i)); } } @@ -1161,136 +1162,264 @@ */ public List subList(int fromIndex, int toIndex) { synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; - if (fromIndex < 0 || toIndex > len || fromIndex > toIndex) + Object[] es = getArray(); + int len = es.length; + int size = toIndex - fromIndex; + if (fromIndex < 0 || toIndex > len || size < 0) throw new IndexOutOfBoundsException(); - return new COWSubList(this, fromIndex, toIndex); + return new COWSubList(es, fromIndex, size); } } /** * Sublist for CopyOnWriteArrayList. */ - private static class COWSubList - extends AbstractList - implements RandomAccess - { - private final CopyOnWriteArrayList l; + private class COWSubList implements List, RandomAccess { private final int offset; private int size; private Object[] expectedArray; - // only call this holding l's lock - COWSubList(CopyOnWriteArrayList list, - int fromIndex, int toIndex) { - // assert Thread.holdsLock(list.lock); - l = list; - expectedArray = l.getArray(); - offset = fromIndex; - size = toIndex - fromIndex; + COWSubList(Object[] es, int offset, int size) { + // assert Thread.holdsLock(lock); + expectedArray = es; + this.offset = offset; + this.size = size; } - // only call this holding l's lock private void checkForComodification() { - // assert Thread.holdsLock(l.lock); - if (l.getArray() != expectedArray) + // assert Thread.holdsLock(lock); + if (getArray() != expectedArray) throw new ConcurrentModificationException(); } private Object[] getArrayChecked() { - // assert Thread.holdsLock(l.lock); - Object[] a = l.getArray(); + // assert Thread.holdsLock(lock); + Object[] a = getArray(); if (a != expectedArray) throw new ConcurrentModificationException(); return a; } - // only call this holding l's lock private void rangeCheck(int index) { - // assert Thread.holdsLock(l.lock); + // assert Thread.holdsLock(lock); if (index < 0 || index >= size) throw new IndexOutOfBoundsException(outOfBounds(index, size)); } + private void rangeCheckForAdd(int index) { + // assert Thread.holdsLock(lock); + if (index < 0 || index > size) + throw new IndexOutOfBoundsException(outOfBounds(index, size)); + } + + public Object[] toArray() { + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + return Arrays.copyOfRange(es, offset, offset + size); + } + + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) { + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + if (a.length < size) + return (T[]) Arrays.copyOfRange( + es, offset, offset + size, a.getClass()); + else { + System.arraycopy(es, offset, a, 0, size); + if (a.length > size) + a[size] = null; + return a; + } + } + + public int indexOf(Object o) { + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + int i = indexOfRange(o, es, offset, offset + size); + return (i == -1) ? -1 : i - offset; + } + + public int lastIndexOf(Object o) { + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + int i = lastIndexOfRange(o, es, offset, offset + size); + return (i == -1) ? -1 : i - offset; + } + + public boolean contains(Object o) { + return indexOf(o) >= 0; + } + + public boolean containsAll(Collection c) { + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + for (Object o : c) + if (indexOfRange(o, es, offset, offset + size) < 0) + return false; + return true; + } + + public boolean isEmpty() { + return size() == 0; + } + + public String toString() { + return Arrays.toString(toArray()); + } + + public int hashCode() { + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + return hashCodeOfRange(es, offset, offset + size); + } + + public boolean equals(Object o) { + if (o == this) + return true; + if (!(o instanceof List)) + return false; + Iterator it = ((List)o).iterator(); + + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + + for (int i = offset, end = offset + size; i < end; i++) + if (!it.hasNext() || !Objects.equals(es[i], it.next())) + return false; + return !it.hasNext(); + } + public E set(int index, E element) { - synchronized (l.lock) { + synchronized (lock) { rangeCheck(index); checkForComodification(); - E x = l.set(offset + index, element); - expectedArray = l.getArray(); + E x = CopyOnWriteArrayList.this.set(offset + index, element); + expectedArray = getArray(); return x; } } public E get(int index) { - synchronized (l.lock) { + synchronized (lock) { rangeCheck(index); checkForComodification(); - return l.get(offset + index); + return CopyOnWriteArrayList.this.get(offset + index); } } public int size() { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); return size; } } public boolean add(E element) { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); - l.add(offset + size, element); - expectedArray = l.getArray(); + CopyOnWriteArrayList.this.add(offset + size, element); + expectedArray = getArray(); size++; } return true; } public void add(int index, E element) { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); - if (index < 0 || index > size) - throw new IndexOutOfBoundsException - (outOfBounds(index, size)); - l.add(offset + index, element); - expectedArray = l.getArray(); + rangeCheckForAdd(index); + CopyOnWriteArrayList.this.add(offset + index, element); + expectedArray = getArray(); size++; } } public boolean addAll(Collection c) { - synchronized (l.lock) { + synchronized (lock) { + final Object[] oldArray = getArrayChecked(); + boolean modified = + CopyOnWriteArrayList.this.addAll(offset + size, c); + size += (expectedArray = getArray()).length - oldArray.length; + return modified; + } + } + + public boolean addAll(int index, Collection c) { + synchronized (lock) { + rangeCheckForAdd(index); final Object[] oldArray = getArrayChecked(); - boolean modified = l.addAll(offset + size, c); - size += (expectedArray = l.getArray()).length - oldArray.length; + boolean modified = + CopyOnWriteArrayList.this.addAll(offset + index, c); + size += (expectedArray = getArray()).length - oldArray.length; return modified; } } public void clear() { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); - l.removeRange(offset, offset + size); - expectedArray = l.getArray(); + removeRange(offset, offset + size); + expectedArray = getArray(); size = 0; } } public E remove(int index) { - synchronized (l.lock) { + synchronized (lock) { rangeCheck(index); checkForComodification(); - E result = l.remove(offset + index); - expectedArray = l.getArray(); + E result = CopyOnWriteArrayList.this.remove(offset + index); + expectedArray = getArray(); size--; return result; } } public boolean remove(Object o) { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); int index = indexOf(o); if (index == -1) @@ -1301,36 +1430,35 @@ } public Iterator iterator() { - synchronized (l.lock) { - checkForComodification(); - return new COWSubListIterator(l, 0, offset, size); - } + return listIterator(0); + } + + public ListIterator listIterator() { + return listIterator(0); } public ListIterator listIterator(int index) { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); - if (index < 0 || index > size) - throw new IndexOutOfBoundsException - (outOfBounds(index, size)); - return new COWSubListIterator(l, index, offset, size); + rangeCheckForAdd(index); + return new COWSubListIterator( + CopyOnWriteArrayList.this, index, offset, size); } } public List subList(int fromIndex, int toIndex) { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); if (fromIndex < 0 || toIndex > size || fromIndex > toIndex) throw new IndexOutOfBoundsException(); - return new COWSubList(l, fromIndex + offset, - toIndex + offset); + return new COWSubList(expectedArray, fromIndex + offset, toIndex - fromIndex); } } public void forEach(Consumer action) { Objects.requireNonNull(action); int i, end; final Object[] es; - synchronized (l.lock) { + synchronized (lock) { es = getArrayChecked(); i = offset; end = i + size; @@ -1340,19 +1468,18 @@ } public void replaceAll(UnaryOperator operator) { - Objects.requireNonNull(operator); - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); - l.replaceAll(operator, offset, offset + size); - expectedArray = l.getArray(); + replaceAllRange(operator, offset, offset + size); + expectedArray = getArray(); } } public void sort(Comparator c) { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); - l.sort(c, offset, offset + size); - expectedArray = l.getArray(); + sortRange(c, offset, offset + size); + expectedArray = getArray(); } } @@ -1372,16 +1499,17 @@ } private boolean bulkRemove(Predicate filter) { - synchronized (l.lock) { + synchronized (lock) { final Object[] oldArray = getArrayChecked(); - boolean modified = l.bulkRemove(filter, offset, offset + size); - size += (expectedArray = l.getArray()).length - oldArray.length; + boolean modified = CopyOnWriteArrayList.this.bulkRemove( + filter, offset, offset + size); + size += (expectedArray = getArray()).length - oldArray.length; return modified; } } public Spliterator spliterator() { - synchronized (l.lock) { + synchronized (lock) { return Spliterators.spliterator( getArrayChecked(), offset, offset + size, Spliterator.IMMUTABLE | Spliterator.ORDERED); @@ -1398,7 +1526,7 @@ COWSubListIterator(List l, int index, int offset, int size) { this.offset = offset; this.size = size; - it = l.listIterator(index+offset); + it = l.listIterator(index + offset); } public boolean hasNext() { @@ -1447,7 +1575,7 @@ @SuppressWarnings("unchecked") public void forEachRemaining(Consumer action) { Objects.requireNonNull(action); - while (nextIndex() < size) { + while (hasNext()) { action.accept(it.next()); } }