--- a/src/java.base/share/classes/java/util/ArrayList.java Tue Jan 30 10:42:13 2018 -0800
+++ b/src/java.base/share/classes/java/util/ArrayList.java Tue Jan 30 11:08:50 2018 -0800
@@ -1143,6 +1143,23 @@
return modified;
}
+ public Object[] toArray() {
+ checkForComodification();
+ return Arrays.copyOfRange(root.elementData, offset, offset + size);
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> 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<E> iterator() {
return listIterator();
}
--- a/test/jdk/java/util/Collection/IteratorMicroBenchmark.java Tue Jan 30 10:42:13 2018 -0800
+++ b/test/jdk/java/util/Collection/IteratorMicroBenchmark.java Tue Jan 30 11:08:50 2018 -0800
@@ -28,7 +28,7 @@
*/
import static java.util.stream.Collectors.summingInt;
-import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toCollection;
import java.lang.ref.WeakReference;
import java.util.ArrayDeque;
@@ -46,6 +46,7 @@
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.LinkedTransferQueue;
@@ -55,6 +56,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;
import java.util.regex.Pattern;
+import java.util.stream.Stream;
/**
* Usage: [iterations=N] [size=N] [filter=REGEXP] [warmup=SECONDS]
@@ -79,7 +81,7 @@
final int size; // number of elements in collections
final double warmupSeconds;
final long warmupNanos;
- final Pattern filter; // select subset of Jobs to run
+ final Pattern nameFilter; // select subset of Jobs to run
final boolean reverse; // reverse order of Jobs
final boolean shuffle; // randomize order of Jobs
@@ -87,7 +89,7 @@
iterations = intArg(args, "iterations", 10_000);
size = intArg(args, "size", 1000);
warmupSeconds = doubleArg(args, "warmup", 7.0);
- filter = patternArg(args, "filter");
+ nameFilter = patternArg(args, "filter");
reverse = booleanArg(args, "reverse");
shuffle = booleanArg(args, "shuffle");
@@ -204,13 +206,6 @@
throw new IllegalArgumentException(val);
}
- private static List<Job> filter(Pattern filter, List<Job> jobs) {
- return (filter == null) ? jobs
- : jobs.stream()
- .filter(job -> filter.matcher(job.name()).find())
- .collect(toList());
- }
-
private static void deoptimize(int sum) {
if (sum == 42)
System.out.println("the answer");
@@ -249,7 +244,7 @@
void run() throws Throwable {
// System.out.printf(
// "iterations=%d size=%d, warmup=%1g, filter=\"%s\"%n",
-// iterations, size, warmupSeconds, filter);
+// iterations, size, warmupSeconds, nameFilter);
final ArrayList<Integer> al = new ArrayList<>(size);
@@ -268,34 +263,48 @@
abq.add(abq.remove());
}
- ArrayList<Job> jobs = new ArrayList<>();
-
- List.<Collection<Integer>>of(
- al, ad, abq,
- new LinkedList<>(al),
- new PriorityQueue<>(al),
- new Vector<>(al),
- new ConcurrentLinkedQueue<>(al),
- new ConcurrentLinkedDeque<>(al),
- new LinkedBlockingQueue<>(al),
- new LinkedBlockingDeque<>(al),
- new LinkedTransferQueue<>(al),
- new PriorityBlockingQueue<>(al)).forEach(
- x -> {
- jobs.addAll(collectionJobs(x));
- if (x instanceof Deque)
- jobs.addAll(dequeJobs((Deque<Integer>)x));
- });
+ ArrayList<Job> jobs = Stream.<Collection<Integer>>of(
+ al, ad, abq,
+ new LinkedList<>(al),
+ new PriorityQueue<>(al),
+ new Vector<>(al),
+ new CopyOnWriteArrayList<>(al),
+ new ConcurrentLinkedQueue<>(al),
+ new ConcurrentLinkedDeque<>(al),
+ new LinkedBlockingQueue<>(al),
+ new LinkedBlockingDeque<>(al),
+ new LinkedTransferQueue<>(al),
+ new PriorityBlockingQueue<>(al))
+ .flatMap(x -> jobs(x))
+ .filter(job ->
+ nameFilter == null || nameFilter.matcher(job.name()).find())
+ .collect(toCollection(ArrayList::new));
if (reverse) Collections.reverse(jobs);
if (shuffle) Collections.shuffle(jobs);
- time(filter(filter, jobs));
+ time(jobs);
+ }
+
+ @SafeVarargs @SuppressWarnings("varargs")
+ private <T> Stream<T> concatStreams(Stream<T> ... streams) {
+ return Stream.of(streams).flatMap(s -> s);
}
- List<Job> collectionJobs(Collection<Integer> x) {
+ Stream<Job> jobs(Collection<Integer> x) {
+ return concatStreams(
+ collectionJobs(x),
+ (x instanceof Deque)
+ ? dequeJobs((Deque<Integer>)x)
+ : Stream.empty(),
+ (x instanceof List)
+ ? listJobs((List<Integer>)x)
+ : Stream.empty());
+ }
+
+ Stream<Job> collectionJobs(Collection<Integer> x) {
String klazz = x.getClass().getSimpleName();
- return List.of(
+ return Stream.of(
new Job(klazz + " iterate for loop") {
public void work() throws Throwable {
for (int i = 0; i < iterations; i++) {
@@ -436,9 +445,9 @@
check.sum(sum[0]);}}});
}
- List<Job> dequeJobs(Deque<Integer> x) {
+ Stream<Job> dequeJobs(Deque<Integer> x) {
String klazz = x.getClass().getSimpleName();
- return List.of(
+ return Stream.of(
new Job(klazz + " descendingIterator() loop") {
public void work() throws Throwable {
for (int i = 0; i < iterations; i++) {
@@ -455,4 +464,50 @@
x.descendingIterator().forEachRemaining(n -> sum[0] += n);
check.sum(sum[0]);}}});
}
+
+ Stream<Job> listJobs(List<Integer> x) {
+ String klazz = x.getClass().getSimpleName();
+ return Stream.of(
+ new Job(klazz + " subList toArray()") {
+ public void work() throws Throwable {
+ int size = x.size();
+ for (int i = 0; i < iterations; i++) {
+ int total = Stream.of(x.subList(0, size / 2),
+ x.subList(size / 2, size))
+ .mapToInt(subList -> {
+ int sum = 0;
+ for (Object o : subList.toArray())
+ sum += (Integer) o;
+ return sum; })
+ .sum();
+ check.sum(total);}}},
+ new Job(klazz + " subList toArray(a)") {
+ public void work() throws Throwable {
+ int size = x.size();
+ for (int i = 0; i < iterations; i++) {
+ int total = Stream.of(x.subList(0, size / 2),
+ x.subList(size / 2, size))
+ .mapToInt(subList -> {
+ int sum = 0;
+ Integer[] a = new Integer[subList.size()];
+ for (Object o : subList.toArray(a))
+ sum += (Integer) o;
+ return sum; })
+ .sum();
+ check.sum(total);}}},
+ new Job(klazz + " subList toArray(empty)") {
+ public void work() throws Throwable {
+ int size = x.size();
+ Integer[] empty = new Integer[0];
+ for (int i = 0; i < iterations; i++) {
+ int total = Stream.of(x.subList(0, size / 2),
+ x.subList(size / 2, size))
+ .mapToInt(subList -> {
+ int sum = 0;
+ for (Object o : subList.toArray(empty))
+ sum += (Integer) o;
+ return sum; })
+ .sum();
+ check.sum(total);}}});
+ }
}