8148115: Stream.findFirst for unordered source optimization
Reviewed-by: psandoz
This commit is contained in:
parent
9e65963f4f
commit
e41fea88e7
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2016, 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
|
||||
@ -107,7 +107,7 @@ final class FindOps {
|
||||
*/
|
||||
private static final class FindOp<T, O> implements TerminalOp<T, O> {
|
||||
private final StreamShape shape;
|
||||
final boolean mustFindFirst;
|
||||
final int opFlags;
|
||||
final O emptyValue;
|
||||
final Predicate<O> presentPredicate;
|
||||
final Supplier<TerminalSink<T, O>> sinkSupplier;
|
||||
@ -129,7 +129,7 @@ final class FindOps {
|
||||
O emptyValue,
|
||||
Predicate<O> presentPredicate,
|
||||
Supplier<TerminalSink<T, O>> sinkSupplier) {
|
||||
this.mustFindFirst = mustFindFirst;
|
||||
this.opFlags = StreamOpFlag.IS_SHORT_CIRCUIT | (mustFindFirst ? 0 : StreamOpFlag.NOT_ORDERED);
|
||||
this.shape = shape;
|
||||
this.emptyValue = emptyValue;
|
||||
this.presentPredicate = presentPredicate;
|
||||
@ -138,7 +138,7 @@ final class FindOps {
|
||||
|
||||
@Override
|
||||
public int getOpFlags() {
|
||||
return StreamOpFlag.IS_SHORT_CIRCUIT | (mustFindFirst ? 0 : StreamOpFlag.NOT_ORDERED);
|
||||
return opFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -156,7 +156,10 @@ final class FindOps {
|
||||
@Override
|
||||
public <P_IN> O evaluateParallel(PipelineHelper<T> helper,
|
||||
Spliterator<P_IN> spliterator) {
|
||||
return new FindTask<>(this, helper, spliterator).invoke();
|
||||
// This takes into account the upstream ops flags and the terminal
|
||||
// op flags and therefore takes into account findFirst or findAny
|
||||
boolean mustFindFirst = StreamOpFlag.ORDERED.isKnown(helper.getStreamAndOpFlags());
|
||||
return new FindTask<>(this, mustFindFirst, helper, spliterator).invoke();
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,16 +253,20 @@ final class FindOps {
|
||||
private static final class FindTask<P_IN, P_OUT, O>
|
||||
extends AbstractShortCircuitTask<P_IN, P_OUT, O, FindTask<P_IN, P_OUT, O>> {
|
||||
private final FindOp<P_OUT, O> op;
|
||||
private final boolean mustFindFirst;
|
||||
|
||||
FindTask(FindOp<P_OUT, O> op,
|
||||
boolean mustFindFirst,
|
||||
PipelineHelper<P_OUT> helper,
|
||||
Spliterator<P_IN> spliterator) {
|
||||
super(helper, spliterator);
|
||||
this.mustFindFirst = mustFindFirst;
|
||||
this.op = op;
|
||||
}
|
||||
|
||||
FindTask(FindTask<P_IN, P_OUT, O> parent, Spliterator<P_IN> spliterator) {
|
||||
super(parent, spliterator);
|
||||
this.mustFindFirst = parent.mustFindFirst;
|
||||
this.op = parent.op;
|
||||
}
|
||||
|
||||
@ -283,7 +290,7 @@ final class FindOps {
|
||||
@Override
|
||||
protected O doLeaf() {
|
||||
O result = helper.wrapAndCopyInto(op.sinkSupplier.get(), spliterator).get();
|
||||
if (!op.mustFindFirst) {
|
||||
if (!mustFindFirst) {
|
||||
if (result != null)
|
||||
shortCircuit(result);
|
||||
return null;
|
||||
@ -300,7 +307,7 @@ final class FindOps {
|
||||
|
||||
@Override
|
||||
public void onCompletion(CountedCompleter<?> caller) {
|
||||
if (op.mustFindFirst) {
|
||||
if (mustFindFirst) {
|
||||
for (FindTask<P_IN, P_OUT, O> child = leftChild, p = null; child != p;
|
||||
p = child, child = rightChild) {
|
||||
O result = child.getLocalResult();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2016, 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
|
||||
@ -47,6 +47,7 @@ import java.util.function.ToLongFunction;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
|
||||
/**
|
||||
* LambdaTestHelpers -- assertion methods and useful objects for lambda test cases
|
||||
@ -400,6 +401,16 @@ public class LambdaTestHelpers {
|
||||
assertEquals(toBoxedMultiset(actual), toBoxedMultiset(expected));
|
||||
}
|
||||
|
||||
public static<T> void assertContains(Optional<T> actual, Iterator<T> it) {
|
||||
actual.ifPresentOrElse(r -> {
|
||||
boolean contained = false;
|
||||
while (!contained && it.hasNext()) {
|
||||
contained = Objects.equals(r, it.next());
|
||||
}
|
||||
assertTrue(contained, "Not found: "+r);
|
||||
}, () -> assertFalse(it.hasNext()));
|
||||
}
|
||||
|
||||
public static void launderAssertion(Runnable r, Supplier<String> additionalInfo) {
|
||||
try {
|
||||
r.run();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2016, 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
|
||||
@ -20,6 +20,12 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8148115
|
||||
*/
|
||||
|
||||
package org.openjdk.tests.java.util.stream;
|
||||
|
||||
import java.util.*;
|
||||
@ -61,18 +67,7 @@ public class FindAnyOpTest extends OpTestCase {
|
||||
|
||||
void exerciseStream(TestData.OfRef<Integer> data, Function<Stream<Integer>, Stream<Integer>> fs) {
|
||||
Optional<Integer> or = withData(data).terminal(fs, s -> s.findAny()).equalator(VALID_ANSWER).exercise();
|
||||
if (or.isPresent()) {
|
||||
Integer r = or.get();
|
||||
Iterator<Integer> it = fs.apply(data.stream()).iterator();
|
||||
boolean contained = false;
|
||||
while (!contained && it.hasNext()) {
|
||||
contained = Objects.equals(r, it.next());
|
||||
}
|
||||
assertTrue(contained);
|
||||
}
|
||||
else {
|
||||
assertFalse(fs.apply(data.stream()).iterator().hasNext());
|
||||
}
|
||||
assertContains(or, fs.apply(data.stream()).iterator());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2016, 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
|
||||
@ -20,6 +20,12 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8148115
|
||||
*/
|
||||
|
||||
package org.openjdk.tests.java.util.stream;
|
||||
|
||||
import java.util.*;
|
||||
@ -59,15 +65,19 @@ public class FindFirstOpTest extends OpTestCase {
|
||||
}
|
||||
|
||||
void exerciseStream(TestData.OfRef<Integer> data, Function<Stream<Integer>, Stream<Integer>> fs) {
|
||||
Optional<Integer> r = exerciseTerminalOps(data, fs, s -> s.findFirst());
|
||||
if (r.isPresent()) {
|
||||
Iterator<Integer> i = fs.apply(data.stream()).iterator();
|
||||
assertTrue(i.hasNext());
|
||||
assertEquals(i.next(), r.get());
|
||||
}
|
||||
else {
|
||||
assertFalse(fs.apply(data.stream()).iterator().hasNext());
|
||||
}
|
||||
Iterator<Integer> i = fs.apply(data.stream()).iterator();
|
||||
Optional<Integer> expected = i.hasNext() ? Optional.of(i.next()) : Optional.empty();
|
||||
withData(data).terminal(fs, s -> s.findFirst())
|
||||
.expectedResult(expected)
|
||||
.resultAsserter((act, exp, ord, par) -> {
|
||||
if (par & !ord) {
|
||||
assertContains(act, fs.apply(data.stream()).iterator());
|
||||
}
|
||||
else {
|
||||
assertEquals(act, exp);
|
||||
}
|
||||
})
|
||||
.exercise();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
|
||||
|
Loading…
x
Reference in New Issue
Block a user