--- jsr166/src/main/java/util/ArrayList.java 2018/05/22 15:51:31 1.62
+++ jsr166/src/main/java/util/ArrayList.java 2020/07/24 20:57:26 1.71
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -28,7 +28,8 @@ package java.util;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
-import jdk.internal.misc.SharedSecrets;
+// OPENJDK import jdk.internal.access.SharedSecrets;
+import jdk.internal.util.ArraysSupport;
/**
* Resizable-array implementation of the {@code List} interface. Implements
@@ -92,7 +93,7 @@ import jdk.internal.misc.SharedSecrets;
* 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
@@ -108,6 +109,7 @@ import jdk.internal.misc.SharedSecrets;
public class ArrayList extends AbstractList
implements List, RandomAccess, Cloneable, java.io.Serializable
{
+ // OPENJDK @java.io.Serial
private static final long serialVersionUID = 8683452581122892189L;
/**
@@ -176,15 +178,16 @@ public class ArrayList extends Abstra
* @throws NullPointerException if the specified collection is null
*/
public ArrayList(Collection extends E> c) {
- elementData = c.toArray();
- if ((size = elementData.length) != 0) {
- // defend against c.toArray (incorrectly) not returning Object[]
- // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
- if (elementData.getClass() != Object[].class)
- elementData = Arrays.copyOf(elementData, size, Object[].class);
+ 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.
- this.elementData = EMPTY_ELEMENTDATA;
+ elementData = EMPTY_ELEMENTDATA;
}
}
@@ -219,14 +222,6 @@ public class ArrayList extends Abstra
}
/**
- * The maximum size of array to allocate (unless necessary).
- * Some VMs reserve some header words in an array.
- * Attempts to allocate larger arrays may result in
- * OutOfMemoryError: Requested array size exceeds VM limit
- */
- private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
-
- /**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
@@ -234,8 +229,15 @@ public class ArrayList extends Abstra
* @throws OutOfMemoryError if minCapacity is less than zero
*/
private Object[] grow(int minCapacity) {
- return elementData = Arrays.copyOf(elementData,
- newCapacity(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)];
+ }
}
private Object[] grow() {
@@ -243,39 +245,6 @@ public class ArrayList extends Abstra
}
/**
- * Returns a capacity at least as large as the given minimum capacity.
- * Returns the current capacity increased by 50% if that suffices.
- * Will not return a capacity greater than MAX_ARRAY_SIZE unless
- * the given minimum capacity is greater than MAX_ARRAY_SIZE.
- *
- * @param minCapacity the desired minimum capacity
- * @throws OutOfMemoryError if minCapacity is less than zero
- */
- private int newCapacity(int minCapacity) {
- // overflow-conscious code
- int oldCapacity = elementData.length;
- int newCapacity = oldCapacity + (oldCapacity >> 1);
- if (newCapacity - minCapacity <= 0) {
- if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
- return Math.max(DEFAULT_CAPACITY, minCapacity);
- if (minCapacity < 0) // overflow
- throw new OutOfMemoryError();
- return minCapacity;
- }
- return (newCapacity - MAX_ARRAY_SIZE <= 0)
- ? newCapacity
- : hugeCapacity(minCapacity);
- }
-
- private static int hugeCapacity(int minCapacity) {
- if (minCapacity < 0) // overflow
- throw new OutOfMemoryError();
- return (minCapacity > MAX_ARRAY_SIZE)
- ? Integer.MAX_VALUE
- : MAX_ARRAY_SIZE;
- }
-
- /**
* Returns the number of elements in this list.
*
* @return the number of elements in this list
@@ -571,7 +540,7 @@ public class ArrayList extends Abstra
if (to > es.length) {
throw new ConcurrentModificationException();
}
- Iterator> oit = other.iterator();
+ var oit = other.iterator();
for (; from < to; from++) {
if (!oit.hasNext() || !Objects.equals(es[from], oit.next())) {
return false;
@@ -888,6 +857,7 @@ public class ArrayList extends Abstra
* instance is emitted (int), followed by all of its elements
* (each an {@code Object}) in the proper order.
*/
+ // OPENJDK @java.io.Serial
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out element count, and any hidden stuff
@@ -915,6 +885,7 @@ public class ArrayList extends Abstra
* could not be found
* @throws java.io.IOException if an I/O error occurs
*/
+ // OPENJDK @java.io.Serial
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
@@ -926,7 +897,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);
+ jsr166.Platform.checkArray(s, Object[].class, size);
Object[] elements = new Object[size];
// Read in all elements in the proper order.
@@ -1169,7 +1140,7 @@ public class ArrayList extends Abstra
this.parent = parent;
this.offset = parent.offset + fromIndex;
this.size = toIndex - fromIndex;
- this.modCount = root.modCount;
+ this.modCount = parent.modCount;
}
public E set(int index, E element) {
@@ -1322,7 +1293,7 @@ public class ArrayList extends Abstra
return new ListIterator() {
int cursor = index;
int lastRet = -1;
- int expectedModCount = root.modCount;
+ int expectedModCount = SubList.this.modCount;
public boolean hasNext() {
return cursor != SubList.this.size;
@@ -1366,7 +1337,7 @@ public class ArrayList extends Abstra
final Object[] es = root.elementData;
if (offset + i >= es.length)
throw new ConcurrentModificationException();
- for (; i < size && modCount == expectedModCount; i++)
+ for (; i < size && root.modCount == expectedModCount; i++)
action.accept(elementAt(es, offset + i));
// update once at end to reduce heap write traffic
cursor = i;
@@ -1392,7 +1363,7 @@ public class ArrayList extends Abstra
SubList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
- expectedModCount = root.modCount;
+ expectedModCount = SubList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
@@ -1418,7 +1389,7 @@ public class ArrayList extends Abstra
SubList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
- expectedModCount = root.modCount;
+ expectedModCount = SubList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
@@ -1737,6 +1708,7 @@ public class ArrayList extends Abstra
@Override
public void replaceAll(UnaryOperator operator) {
replaceAllRange(operator, 0, size);
+ // TODO(8203662): remove increment of modCount from ...
modCount++;
}