--- jsr166/src/main/java/util/ArrayList.java 2017/05/06 06:49:45 1.50 +++ jsr166/src/main/java/util/ArrayList.java 2018/05/05 18:29:53 1.58 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -28,6 +28,7 @@ package java.util; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.UnaryOperator; +import jdk.internal.misc.SharedSecrets; /** * Resizable-array implementation of the {@code List} interface. Implements @@ -515,15 +516,10 @@ public class ArrayList extends Abstra */ public E remove(int index) { Objects.checkIndex(index, size); + final Object[] es = elementData; - modCount++; - E oldValue = elementData(index); - - int numMoved = size - index - 1; - if (numMoved > 0) - System.arraycopy(elementData, index+1, elementData, index, - numMoved); - elementData[--size] = null; // clear to let GC do its work + @SuppressWarnings("unchecked") E oldValue = (E) es[index]; + fastRemove(es, index); // checkInvariants(); return oldValue; @@ -543,33 +539,35 @@ public class ArrayList extends Abstra * @return {@code true} if this list contained the specified element */ public boolean remove(Object o) { - if (o == null) { - for (int index = 0; index < size; index++) - if (elementData[index] == null) { - fastRemove(index); - return true; - } - } else { - for (int index = 0; index < size; index++) - if (o.equals(elementData[index])) { - fastRemove(index); - return true; - } + final Object[] es = elementData; + final int 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; + } + return false; } - return false; + fastRemove(es, i); + return true; } /** * Private remove method that skips bounds checking and does not * return the value removed. */ - private void fastRemove(int index) { + private void fastRemove(Object[] es, int i) { modCount++; - int numMoved = size - index - 1; - if (numMoved > 0) - System.arraycopy(elementData, index+1, elementData, index, - numMoved); - elementData[--size] = null; // clear to let GC do its work + final int newSize; + if ((newSize = size - 1) > i) + System.arraycopy(es, i + 1, es, i, newSize - i); + es[size = newSize] = null; } /** @@ -748,30 +746,31 @@ public class ArrayList extends Abstra final int from, final int end) { Objects.requireNonNull(c); final Object[] es = elementData; - final boolean modified; int r; // Optimize for initial run of survivors - for (r = from; r < end && c.contains(es[r]) == complement; r++) - ; - if (modified = (r < end)) { - 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); - } + for (r = from;; r++) { + if (r == end) + return false; + 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); } // checkInvariants(); - return modified; + return true; } /** @@ -790,7 +789,7 @@ public class ArrayList extends Abstra int expectedModCount = modCount; s.defaultWriteObject(); - // Write out size as capacity for behavioural compatibility with clone() + // Write out size as capacity for behavioral compatibility with clone() s.writeInt(size); // Write out all elements in the proper order. @@ -822,6 +821,7 @@ public class ArrayList extends Abstra 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. @@ -1122,6 +1122,10 @@ public class ArrayList extends Abstra return true; } + public void replaceAll(UnaryOperator operator) { + root.replaceAllRange(operator, offset, offset + size); + } + public boolean removeAll(Collection c) { return batchRemove(c, false); } @@ -1149,6 +1153,23 @@ public class ArrayList extends Abstra return modified; } + public Object[] toArray() { + checkForComodification(); + return Arrays.copyOfRange(root.elementData, offset, offset + size); + } + + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) { + checkForComodification(); + if (a.length < size) + return (T[]) Arrays.copyOfRange( + root.elementData, offset, offset + size, a.getClass()); + System.arraycopy(root.elementData, offset, a, 0, size); + if (a.length > size) + a[size] = null; + return a; + } + public Iterator iterator() { return listIterator(); } @@ -1556,7 +1577,6 @@ public class ArrayList extends Abstra setBit(deathRow, i - beg); if (modCount != expectedModCount) throw new ConcurrentModificationException(); - expectedModCount++; modCount++; int w = beg; for (i = beg; i < end; i++) @@ -1575,15 +1595,17 @@ public class ArrayList extends Abstra @Override public void replaceAll(UnaryOperator operator) { + replaceAllRange(operator, 0, size); + } + + private void replaceAllRange(UnaryOperator operator, int from, int to) { Objects.requireNonNull(operator); final int expectedModCount = modCount; final Object[] es = elementData; - final int size = this.size; - for (int i = 0; modCount == expectedModCount && i < size; i++) + for (int i = from; modCount == expectedModCount && i < to; i++) es[i] = operator.apply(elementAt(es, i)); if (modCount != expectedModCount) throw new ConcurrentModificationException(); - modCount++; // checkInvariants(); }