--- jsr166/src/main/java/util/ArrayList.java 2016/11/16 00:17:25 1.44
+++ jsr166/src/main/java/util/ArrayList.java 2017/05/06 06:49:45 1.50
@@ -91,7 +91,7 @@ import java.util.function.UnaryOperator;
* should be used only to detect bugs.
*
*
This class is a member of the
- *
+ *
* Java Collections Framework.
*
* @param the type of elements in this list
@@ -578,8 +578,9 @@ public class ArrayList extends Abstra
*/
public void clear() {
modCount++;
- Arrays.fill(elementData, 0, size, null);
- size = 0;
+ final Object[] es = elementData;
+ for (int to = size, i = size = 0; i < to; i++)
+ es[i] = null;
}
/**
@@ -669,13 +670,17 @@ public class ArrayList extends Abstra
outOfBoundsMsg(fromIndex, toIndex));
}
modCount++;
- final Object[] es = elementData;
- final int oldSize = size;
- System.arraycopy(es, toIndex, es, fromIndex, oldSize - toIndex);
- Arrays.fill(es, size -= (toIndex - fromIndex), oldSize, null);
+ shiftTailOverGap(elementData, fromIndex, toIndex);
// checkInvariants();
}
+ /** Erases the gap from lo to hi, by sliding down following elements. */
+ private void 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.
*/
@@ -761,10 +766,8 @@ public class ArrayList extends Abstra
w += end - r;
throw ex;
} finally {
- final int oldSize = size, deleted = end - w;
- modCount += deleted;
- System.arraycopy(es, end, es, w, oldSize - end);
- Arrays.fill(es, size -= deleted, oldSize, null);
+ modCount += end - w;
+ shiftTailOverGap(es, w, end);
}
}
// checkInvariants();
@@ -772,15 +775,17 @@ public class ArrayList extends Abstra
}
/**
- * Save the state of the {@code ArrayList} instance to a stream (that
- * is, serialize it).
+ * 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.
*/
private void writeObject(java.io.ObjectOutputStream s)
- throws java.io.IOException{
+ throws java.io.IOException {
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
@@ -799,8 +804,12 @@ public class ArrayList extends Abstra
}
/**
- * Reconstitute the {@code ArrayList} instance from a stream (that is,
- * deserialize it).
+ * 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
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
@@ -1291,9 +1300,8 @@ public class ArrayList extends Abstra
public Spliterator spliterator() {
checkForComodification();
- // ArrayListSpliterator is not used because late-binding logic
- // is different here
- return new Spliterator<>() {
+ // ArrayListSpliterator not used here due to late-binding
+ return new Spliterator() {
private int index = offset; // current index, modified on advance/split
private int fence = -1; // -1 until used; then one past last index
private int expectedModCount; // initialized when fence set
@@ -1307,12 +1315,11 @@ public class ArrayList extends Abstra
return hi;
}
- public ArrayListSpliterator trySplit() {
+ public ArrayList.ArrayListSpliterator trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
- // ArrayListSpliterator could be used here as the source is already bound
+ // ArrayListSpliterator can be used here as the source is already bound
return (lo >= mid) ? null : // divide range in half unless too small
- new ArrayListSpliterator<>(root, lo, index = mid,
- expectedModCount);
+ root.new ArrayListSpliterator(lo, index = mid, expectedModCount);
}
public boolean tryAdvance(Consumer super E> action) {
@@ -1354,7 +1361,7 @@ public class ArrayList extends Abstra
}
public long estimateSize() {
- return (long) (getFence() - index);
+ return getFence() - index;
}
public int characteristics() {
@@ -1364,6 +1371,9 @@ public class ArrayList extends Abstra
}
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
@Override
public void forEach(Consumer super E> action) {
Objects.requireNonNull(action);
@@ -1391,11 +1401,11 @@ public class ArrayList extends Abstra
*/
@Override
public Spliterator spliterator() {
- return new ArrayListSpliterator<>(this, 0, -1, 0);
+ return new ArrayListSpliterator(0, -1, 0);
}
/** Index-based split-by-two, lazily initialized Spliterator */
- static final class ArrayListSpliterator implements Spliterator {
+ final class ArrayListSpliterator implements Spliterator {
/*
* If ArrayLists were immutable, or structurally immutable (no
@@ -1429,15 +1439,12 @@ public class ArrayList extends Abstra
* these streamlinings.
*/
- private final ArrayList list;
private int index; // current index, modified on advance/split
private int fence; // -1 until used; then one past last index
private int expectedModCount; // initialized when fence set
- /** Create new spliterator covering the given range */
- ArrayListSpliterator(ArrayList list, int origin, int fence,
- int expectedModCount) {
- this.list = list; // OK if null unless traversed
+ /** Creates new spliterator covering the given range. */
+ ArrayListSpliterator(int origin, int fence, int expectedModCount) {
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
@@ -1445,23 +1452,17 @@ public class ArrayList extends Abstra
private int getFence() { // initialize fence to size on first use
int hi; // (a specialized variant appears in method forEach)
- ArrayList lst;
if ((hi = fence) < 0) {
- if ((lst = list) == null)
- hi = fence = 0;
- else {
- expectedModCount = lst.modCount;
- hi = fence = lst.size;
- }
+ expectedModCount = modCount;
+ hi = fence = size;
}
return hi;
}
- public ArrayListSpliterator trySplit() {
+ 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<>(list, lo, index = mid,
- expectedModCount);
+ new ArrayListSpliterator(lo, index = mid, expectedModCount);
}
public boolean tryAdvance(Consumer super E> action) {
@@ -1470,9 +1471,9 @@ public class ArrayList extends Abstra
int hi = getFence(), i = index;
if (i < hi) {
index = i + 1;
- @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
+ @SuppressWarnings("unchecked") E e = (E)elementData[i];
action.accept(e);
- if (list.modCount != expectedModCount)
+ if (modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
@@ -1481,13 +1482,13 @@ public class ArrayList extends Abstra
public void forEachRemaining(Consumer super E> action) {
int i, hi, mc; // hoist accesses and checks from loop
- ArrayList lst; Object[] a;
+ Object[] a;
if (action == null)
throw new NullPointerException();
- if ((lst = list) != null && (a = lst.elementData) != null) {
+ if ((a = elementData) != null) {
if ((hi = fence) < 0) {
- mc = lst.modCount;
- hi = lst.size;
+ mc = modCount;
+ hi = size;
}
else
mc = expectedModCount;
@@ -1496,7 +1497,7 @@ public class ArrayList extends Abstra
@SuppressWarnings("unchecked") E e = (E) a[i];
action.accept(e);
}
- if (lst.modCount == mc)
+ if (modCount == mc)
return;
}
}
@@ -1504,7 +1505,7 @@ public class ArrayList extends Abstra
}
public long estimateSize() {
- return (long) (getFence() - index);
+ return getFence() - index;
}
public int characteristics() {
@@ -1524,6 +1525,9 @@ public class ArrayList extends Abstra
return (bits[i >> 6] & (1L << i)) == 0;
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
@Override
public boolean removeIf(Predicate super E> filter) {
return removeIf(filter, 0, size);
@@ -1558,9 +1562,7 @@ public class ArrayList extends Abstra
for (i = beg; i < end; i++)
if (isClear(deathRow, i - beg))
es[w++] = es[i];
- final int oldSize = size;
- System.arraycopy(es, end, es, w, oldSize - end);
- Arrays.fill(es, size -= (end - w), oldSize, null);
+ shiftTailOverGap(es, w, end);
// checkInvariants();
return true;
} else {