--- jsr166/src/main/java/util/ArrayList.java 2017/05/31 22:37:31 1.52
+++ jsr166/src/main/java/util/ArrayList.java 2018/11/11 16:27:28 1.65
@@ -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;
+// OPENJDK import jdk.internal.access.SharedSecrets;
/**
* Resizable-array implementation of the {@code List} interface. Implements
@@ -91,7 +92,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
@@ -313,14 +314,23 @@ public class ArrayList extends Abstra
* or -1 if there is no such index.
*/
public int 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 = 0; i < size; i++)
- if (elementData[i]==null)
+ for (int i = start; i < end; i++) {
+ if (es[i] == null) {
return i;
+ }
+ }
} else {
- for (int i = 0; i < size; i++)
- if (o.equals(elementData[i]))
+ for (int i = start; i < end; i++) {
+ if (o.equals(es[i])) {
return i;
+ }
+ }
}
return -1;
}
@@ -333,14 +343,23 @@ public class ArrayList extends Abstra
* or -1 if there is no such index.
*/
public int 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 = size-1; i >= 0; i--)
- if (elementData[i]==null)
+ for (int i = end - 1; i >= start; i--) {
+ if (es[i] == null) {
return i;
+ }
+ }
} else {
- for (int i = size-1; i >= 0; i--)
- if (o.equals(elementData[i]))
+ for (int i = end - 1; i >= start; i--) {
+ if (o.equals(es[i])) {
return i;
+ }
+ }
}
return -1;
}
@@ -525,6 +544,93 @@ public class ArrayList extends Abstra
}
/**
+ * {@inheritDoc}
+ */
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+
+ if (!(o instanceof List)) {
+ return false;
+ }
+
+ final int 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);
+
+ checkForComodification(expectedModCount);
+ return equal;
+ }
+
+ boolean equalsRange(List> other, int from, int to) {
+ final Object[] es = elementData;
+ if (to > es.length) {
+ throw new ConcurrentModificationException();
+ }
+ Iterator> oit = other.iterator();
+ for (; from < to; from++) {
+ if (!oit.hasNext() || !Objects.equals(es[from], oit.next())) {
+ return false;
+ }
+ }
+ return !oit.hasNext();
+ }
+
+ private boolean equalsArrayList(ArrayList> other) {
+ final int otherModCount = other.modCount;
+ final int 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) {
+ throw new ConcurrentModificationException();
+ }
+ for (int i = 0; i < s; i++) {
+ if (!Objects.equals(es[i], otherEs[i])) {
+ equal = false;
+ break;
+ }
+ }
+ }
+ other.checkForComodification(otherModCount);
+ return equal;
+ }
+
+ private void checkForComodification(final int expectedModCount) {
+ if (modCount != expectedModCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int 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) {
+ throw new 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
@@ -745,30 +851,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;
}
/**
@@ -819,6 +926,7 @@ public class ArrayList extends Abstra
if (size > 0) {
// like clone(), allocate array based upon size not capacity
+ jsr166.Platform.checkArray(s, Object[].class, size);
Object[] elements = new Object[size];
// Read in all elements in the proper order.
@@ -1119,6 +1227,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);
}
@@ -1146,6 +1258,59 @@ 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 boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+
+ if (!(o instanceof List)) {
+ return false;
+ }
+
+ boolean equal = root.equalsRange((List>)o, offset, offset + size);
+ checkForComodification();
+ return equal;
+ }
+
+ public int hashCode() {
+ int hash = root.hashCodeRange(offset, offset + size);
+ checkForComodification();
+ return hash;
+ }
+
+ public int indexOf(Object o) {
+ int index = root.indexOfRange(o, offset, offset + size);
+ checkForComodification();
+ return index >= 0 ? index - offset : -1;
+ }
+
+ public int lastIndexOf(Object o) {
+ int index = root.lastIndexOfRange(o, offset, offset + size);
+ checkForComodification();
+ return index >= 0 ? index - offset : -1;
+ }
+
+ public boolean contains(Object o) {
+ return indexOf(o) >= 0;
+ }
+
public Iterator iterator() {
return listIterator();
}
@@ -1553,7 +1718,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++)
@@ -1572,15 +1736,17 @@ public class ArrayList extends Abstra
@Override
public void replaceAll(UnaryOperator operator) {
+ replaceAllRange(operator, 0, size);
+ }
+
+ private void replaceAllRange(UnaryOperator operator, int i, int end) {
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 (; modCount == expectedModCount && i < end; i++)
es[i] = operator.apply(elementAt(es, i));
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
- modCount++;
// checkInvariants();
}