8015315: Stream.concat methods
Co-authored-by: Henry Jen <henry.jen@oracle.com> Reviewed-by: psandoz, mduigou
This commit is contained in:
parent
53edbe01cb
commit
4e416d4714
@ -746,4 +746,26 @@ public interface DoubleStream extends BaseStream<Double, DoubleStream> {
|
||||
return StreamSupport.doubleStream(
|
||||
new StreamSpliterators.InfiniteSupplyingSpliterator.OfDouble(Long.MAX_VALUE, s));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a lazy concatenated {@code DoubleStream} whose elements are all the
|
||||
* elements of a first {@code DoubleStream} succeeded by all the elements of the
|
||||
* second {@code DoubleStream}. The resulting stream is ordered if both
|
||||
* of the input streams are ordered, and parallel if either of the input
|
||||
* streams is parallel.
|
||||
*
|
||||
* @param a the first stream
|
||||
* @param b the second stream to concatenate on to end of the first stream
|
||||
* @return the concatenation of the two streams
|
||||
*/
|
||||
public static DoubleStream concat(DoubleStream a, DoubleStream b) {
|
||||
Objects.requireNonNull(a);
|
||||
Objects.requireNonNull(b);
|
||||
|
||||
Spliterator.OfDouble split = new Streams.ConcatSpliterator.OfDouble(
|
||||
a.spliterator(), b.spliterator());
|
||||
return (a.isParallel() || b.isParallel())
|
||||
? StreamSupport.doubleParallelStream(split)
|
||||
: StreamSupport.doubleStream(split);
|
||||
}
|
||||
}
|
||||
|
@ -800,4 +800,26 @@ public interface IntStream extends BaseStream<Integer, IntStream> {
|
||||
new Streams.RangeIntSpliterator(startInclusive, endInclusive, true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a lazy concatenated {@code IntStream} whose elements are all the
|
||||
* elements of a first {@code IntStream} succeeded by all the elements of the
|
||||
* second {@code IntStream}. The resulting stream is ordered if both
|
||||
* of the input streams are ordered, and parallel if either of the input
|
||||
* streams is parallel.
|
||||
*
|
||||
* @param a the first stream
|
||||
* @param b the second stream to concatenate on to end of the first stream
|
||||
* @return the concatenation of the two streams
|
||||
*/
|
||||
public static IntStream concat(IntStream a, IntStream b) {
|
||||
Objects.requireNonNull(a);
|
||||
Objects.requireNonNull(b);
|
||||
|
||||
Spliterator.OfInt split = new Streams.ConcatSpliterator.OfInt(
|
||||
a.spliterator(), b.spliterator());
|
||||
return (a.isParallel() || b.isParallel())
|
||||
? StreamSupport.intParallelStream(split)
|
||||
: StreamSupport.intStream(split);
|
||||
}
|
||||
}
|
||||
|
@ -765,10 +765,8 @@ public interface LongStream extends BaseStream<Long, LongStream> {
|
||||
// Split the range in two and concatenate
|
||||
// Note: if the range is [Long.MIN_VALUE, Long.MAX_VALUE) then
|
||||
// the lower range, [Long.MIN_VALUE, 0) will be further split in two
|
||||
// long m = startInclusive + Long.divideUnsigned(endExclusive - startInclusive, 2) + 1;
|
||||
// return Streams.concat(range(startInclusive, m), range(m, endExclusive));
|
||||
// This is temporary until Streams.concat is supported
|
||||
throw new UnsupportedOperationException();
|
||||
long m = startInclusive + Long.divideUnsigned(endExclusive - startInclusive, 2) + 1;
|
||||
return concat(range(startInclusive, m), range(m, endExclusive));
|
||||
} else {
|
||||
return StreamSupport.longStream(
|
||||
new Streams.RangeLongSpliterator(startInclusive, endExclusive, false));
|
||||
@ -801,13 +799,33 @@ public interface LongStream extends BaseStream<Long, LongStream> {
|
||||
// Note: if the range is [Long.MIN_VALUE, Long.MAX_VALUE] then
|
||||
// the lower range, [Long.MIN_VALUE, 0), and upper range,
|
||||
// [0, Long.MAX_VALUE], will both be further split in two
|
||||
// long m = startInclusive + Long.divideUnsigned(endInclusive - startInclusive, 2) + 1;
|
||||
// return Streams.concat(range(startInclusive, m), rangeClosed(m, endInclusive));
|
||||
// This is temporary until Streams.concat is supported
|
||||
throw new UnsupportedOperationException();
|
||||
long m = startInclusive + Long.divideUnsigned(endInclusive - startInclusive, 2) + 1;
|
||||
return concat(range(startInclusive, m), rangeClosed(m, endInclusive));
|
||||
} else {
|
||||
return StreamSupport.longStream(
|
||||
new Streams.RangeLongSpliterator(startInclusive, endInclusive, true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a lazy concatenated {@code LongStream} whose elements are all the
|
||||
* elements of a first {@code LongStream} succeeded by all the elements of the
|
||||
* second {@code LongStream}. The resulting stream is ordered if both
|
||||
* of the input streams are ordered, and parallel if either of the input
|
||||
* streams is parallel.
|
||||
*
|
||||
* @param a the first stream
|
||||
* @param b the second stream to concatenate on to end of the first stream
|
||||
* @return the concatenation of the two streams
|
||||
*/
|
||||
public static LongStream concat(LongStream a, LongStream b) {
|
||||
Objects.requireNonNull(a);
|
||||
Objects.requireNonNull(b);
|
||||
|
||||
Spliterator.OfLong split = new Streams.ConcatSpliterator.OfLong(
|
||||
a.spliterator(), b.spliterator());
|
||||
return (a.isParallel() || b.isParallel())
|
||||
? StreamSupport.longParallelStream(split)
|
||||
: StreamSupport.longStream(split);
|
||||
}
|
||||
}
|
||||
|
@ -883,4 +883,29 @@ public interface Stream<T> extends BaseStream<T, Stream<T>> {
|
||||
return StreamSupport.stream(
|
||||
new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a lazy concatenated {@code Stream} whose elements are all the
|
||||
* elements of a first {@code Stream} succeeded by all the elements of the
|
||||
* second {@code Stream}. The resulting stream is ordered if both
|
||||
* of the input streams are ordered, and parallel if either of the input
|
||||
* streams is parallel.
|
||||
*
|
||||
* @param <T> The type of stream elements
|
||||
* @param a the first stream
|
||||
* @param b the second stream to concatenate on to end of the first
|
||||
* stream
|
||||
* @return the concatenation of the two input streams
|
||||
*/
|
||||
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
|
||||
Objects.requireNonNull(a);
|
||||
Objects.requireNonNull(b);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Spliterator<T> split = new Streams.ConcatSpliterator.OfRef<>(
|
||||
(Spliterator<T>) a.spliterator(), (Spliterator<T>) b.spliterator());
|
||||
return (a.isParallel() || b.isParallel())
|
||||
? StreamSupport.parallelStream(split)
|
||||
: StreamSupport.stream(split);
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ import java.util.function.LongConsumer;
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
class Streams {
|
||||
final class Streams {
|
||||
|
||||
private Streams() {
|
||||
throw new Error("no instances");
|
||||
@ -670,4 +670,147 @@ class Streams {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract static class ConcatSpliterator<T, T_SPLITR extends Spliterator<T>>
|
||||
implements Spliterator<T> {
|
||||
protected final T_SPLITR aSpliterator;
|
||||
protected final T_SPLITR bSpliterator;
|
||||
// True when no split has occurred, otherwise false
|
||||
boolean beforeSplit;
|
||||
// Never read after splitting
|
||||
final boolean unsized;
|
||||
|
||||
public ConcatSpliterator(T_SPLITR aSpliterator, T_SPLITR bSpliterator) {
|
||||
this.aSpliterator = aSpliterator;
|
||||
this.bSpliterator = bSpliterator;
|
||||
beforeSplit = true;
|
||||
// The spliterator is unsized before splitting if a and b are
|
||||
// sized and the sum of the estimates overflows
|
||||
unsized = aSpliterator.hasCharacteristics(SIZED)
|
||||
&& aSpliterator.hasCharacteristics(SIZED)
|
||||
&& aSpliterator.estimateSize() + bSpliterator.estimateSize() < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T_SPLITR trySplit() {
|
||||
T_SPLITR ret = beforeSplit ? aSpliterator : (T_SPLITR) bSpliterator.trySplit();
|
||||
beforeSplit = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(Consumer<? super T> consumer) {
|
||||
boolean hasNext;
|
||||
if (beforeSplit) {
|
||||
hasNext = aSpliterator.tryAdvance(consumer);
|
||||
if (!hasNext) {
|
||||
beforeSplit = false;
|
||||
hasNext = bSpliterator.tryAdvance(consumer);
|
||||
}
|
||||
}
|
||||
else
|
||||
hasNext = bSpliterator.tryAdvance(consumer);
|
||||
return hasNext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(Consumer<? super T> consumer) {
|
||||
if (beforeSplit)
|
||||
aSpliterator.forEachRemaining(consumer);
|
||||
bSpliterator.forEachRemaining(consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() {
|
||||
if (beforeSplit) {
|
||||
// If one or both estimates are Long.MAX_VALUE then the sum
|
||||
// will either be Long.MAX_VALUE or overflow to a negative value
|
||||
long size = aSpliterator.estimateSize() + bSpliterator.estimateSize();
|
||||
return (size >= 0) ? size : Long.MAX_VALUE;
|
||||
}
|
||||
else {
|
||||
return bSpliterator.estimateSize();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int characteristics() {
|
||||
if (beforeSplit) {
|
||||
// Concatenation loses DISTINCT and SORTED characteristics
|
||||
return aSpliterator.characteristics() & bSpliterator.characteristics()
|
||||
& ~(Spliterator.DISTINCT | Spliterator.SORTED
|
||||
| (unsized ? Spliterator.SIZED | Spliterator.SUBSIZED : 0));
|
||||
}
|
||||
else {
|
||||
return bSpliterator.characteristics();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comparator<? super T> getComparator() {
|
||||
if (beforeSplit)
|
||||
throw new IllegalStateException();
|
||||
return bSpliterator.getComparator();
|
||||
}
|
||||
|
||||
static class OfRef<T> extends ConcatSpliterator<T, Spliterator<T>> {
|
||||
OfRef(Spliterator<T> aSpliterator, Spliterator<T> bSpliterator) {
|
||||
super(aSpliterator, bSpliterator);
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
|
||||
extends ConcatSpliterator<T, T_SPLITR>
|
||||
implements Spliterator.OfPrimitive<T, T_CONS, T_SPLITR> {
|
||||
private OfPrimitive(T_SPLITR aSpliterator, T_SPLITR bSpliterator) {
|
||||
super(aSpliterator, bSpliterator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(T_CONS action) {
|
||||
boolean hasNext;
|
||||
if (beforeSplit) {
|
||||
hasNext = aSpliterator.tryAdvance(action);
|
||||
if (!hasNext) {
|
||||
beforeSplit = false;
|
||||
hasNext = bSpliterator.tryAdvance(action);
|
||||
}
|
||||
}
|
||||
else
|
||||
hasNext = bSpliterator.tryAdvance(action);
|
||||
return hasNext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(T_CONS action) {
|
||||
if (beforeSplit)
|
||||
aSpliterator.forEachRemaining(action);
|
||||
bSpliterator.forEachRemaining(action);
|
||||
}
|
||||
}
|
||||
|
||||
static class OfInt
|
||||
extends ConcatSpliterator.OfPrimitive<Integer, IntConsumer, Spliterator.OfInt>
|
||||
implements Spliterator.OfInt {
|
||||
OfInt(Spliterator.OfInt aSpliterator, Spliterator.OfInt bSpliterator) {
|
||||
super(aSpliterator, bSpliterator);
|
||||
}
|
||||
}
|
||||
|
||||
static class OfLong
|
||||
extends ConcatSpliterator.OfPrimitive<Long, LongConsumer, Spliterator.OfLong>
|
||||
implements Spliterator.OfLong {
|
||||
OfLong(Spliterator.OfLong aSpliterator, Spliterator.OfLong bSpliterator) {
|
||||
super(aSpliterator, bSpliterator);
|
||||
}
|
||||
}
|
||||
|
||||
static class OfDouble
|
||||
extends ConcatSpliterator.OfPrimitive<Double, DoubleConsumer, Spliterator.OfDouble>
|
||||
implements Spliterator.OfDouble {
|
||||
OfDouble(Spliterator.OfDouble aSpliterator, Spliterator.OfDouble bSpliterator) {
|
||||
super(aSpliterator, bSpliterator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -360,35 +360,26 @@ public class LambdaTestHelpers {
|
||||
private static<T> Map<T, Integer> toBoxedMultiset(Iterator<T> it) {
|
||||
Map<Object, Integer> result = new HashMap<>();
|
||||
|
||||
it.forEachRemaining(new OmnivorousConsumer<T>() {
|
||||
@Override
|
||||
public void accept(T t) {
|
||||
add(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(int value) {
|
||||
add(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(long value) {
|
||||
add(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(double value) {
|
||||
add(value);
|
||||
}
|
||||
|
||||
void add(Object o) {
|
||||
it.forEachRemaining(toBoxingConsumer(o -> {
|
||||
if (result.containsKey(o))
|
||||
result.put(o, result.get(o) + 1);
|
||||
else
|
||||
result.put(o, 1);
|
||||
}
|
||||
}));
|
||||
|
||||
});
|
||||
return (Map<T, Integer>) result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static<T> Map<T, Integer> toBoxedMultiset(Spliterator<T> it) {
|
||||
Map<Object, Integer> result = new HashMap<>();
|
||||
|
||||
it.forEachRemaining(toBoxingConsumer(o -> {
|
||||
if (result.containsKey(o))
|
||||
result.put(o, result.get(o) + 1);
|
||||
else
|
||||
result.put(o, 1);
|
||||
}));
|
||||
|
||||
return (Map<T, Integer>) result;
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package org.openjdk.tests.java.util.stream;
|
||||
|
||||
import java.util.stream.OpTestCase;
|
||||
import java.util.stream.StreamTestDataProvider;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.LongStream;
|
||||
import java.util.stream.DoubleStream;
|
||||
import java.util.stream.TestData;
|
||||
|
||||
import static java.util.stream.LambdaTestHelpers.*;
|
||||
|
||||
public class ConcatOpTest extends OpTestCase {
|
||||
|
||||
// Sanity to make sure all type of stream source works
|
||||
@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
|
||||
public void testOpsSequential(String name, TestData.OfRef<Integer> data) {
|
||||
exerciseOpsInt(data,
|
||||
s -> Stream.concat(s, data.stream()),
|
||||
s -> IntStream.concat(s, data.stream().mapToInt(Integer::intValue)),
|
||||
s -> LongStream.concat(s, data.stream().mapToLong(Integer::longValue)),
|
||||
s -> DoubleStream.concat(s, data.stream().mapToDouble(Integer::doubleValue)));
|
||||
}
|
||||
}
|
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package org.openjdk.tests.java.util.stream;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Factory;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Spliterator;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.DoubleStream;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.LongStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.LambdaTestHelpers.*;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
@Test
|
||||
public class ConcatTest {
|
||||
private static Object[][] cases;
|
||||
|
||||
static {
|
||||
List<Integer> part1 = Arrays.asList(5, 3, 4, 1, 2, 6, 2, 4);
|
||||
List<Integer> part2 = Arrays.asList(8, 8, 6, 6, 9, 7, 10, 9);
|
||||
List<Integer> p1p2 = Arrays.asList(5, 3, 4, 1, 2, 6, 2, 4, 8, 8, 6, 6, 9, 7, 10, 9);
|
||||
List<Integer> p2p1 = Arrays.asList(8, 8, 6, 6, 9, 7, 10, 9, 5, 3, 4, 1, 2, 6, 2, 4);
|
||||
List<Integer> empty = new LinkedList<>(); // To be ordered
|
||||
assertTrue(empty.isEmpty());
|
||||
LinkedHashSet<Integer> distinctP1 = new LinkedHashSet<>(part1);
|
||||
LinkedHashSet<Integer> distinctP2 = new LinkedHashSet<>(part2);
|
||||
TreeSet<Integer> sortedP1 = new TreeSet<>(part1);
|
||||
TreeSet<Integer> sortedP2 = new TreeSet<>(part2);
|
||||
|
||||
cases = new Object[][] {
|
||||
{ "regular", part1, part2, p1p2 },
|
||||
{ "reverse regular", part2, part1, p2p1 },
|
||||
{ "front distinct", distinctP1, part2, Arrays.asList(5, 3, 4, 1, 2, 6, 8, 8, 6, 6, 9, 7, 10, 9) },
|
||||
{ "back distinct", part1, distinctP2, Arrays.asList(5, 3, 4, 1, 2, 6, 2, 4, 8, 6, 9, 7, 10) },
|
||||
{ "both distinct", distinctP1, distinctP2, Arrays.asList(5, 3, 4, 1, 2, 6, 8, 6, 9, 7, 10) },
|
||||
{ "front sorted", sortedP1, part2, Arrays.asList(1, 2, 3, 4, 5, 6, 8, 8, 6, 6, 9, 7, 10, 9) },
|
||||
{ "back sorted", part1, sortedP2, Arrays.asList(5, 3, 4, 1, 2, 6, 2, 4, 6, 7, 8, 9, 10) },
|
||||
{ "both sorted", sortedP1, sortedP2, Arrays.asList(1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 10) },
|
||||
{ "reverse both sorted", sortedP2, sortedP1, Arrays.asList(6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6) },
|
||||
{ "empty something", empty, part1, part1 },
|
||||
{ "something empty", part1, empty, part1 },
|
||||
{ "empty empty", empty, empty, empty }
|
||||
};
|
||||
}
|
||||
|
||||
@DataProvider(name = "cases")
|
||||
private static Object[][] getCases() {
|
||||
return cases;
|
||||
}
|
||||
|
||||
@Factory(dataProvider = "cases")
|
||||
public static Object[] createTests(String scenario, Collection<Integer> c1, Collection<Integer> c2, Collection<Integer> expected) {
|
||||
return new Object[] {
|
||||
new ConcatTest(scenario, c1, c2, expected)
|
||||
};
|
||||
}
|
||||
|
||||
protected final String scenario;
|
||||
protected final Collection<Integer> c1;
|
||||
protected final Collection<Integer> c2;
|
||||
protected final Collection<Integer> expected;
|
||||
|
||||
public ConcatTest(String scenario, Collection<Integer> c1, Collection<Integer> c2, Collection<Integer> expected) {
|
||||
this.scenario = scenario;
|
||||
this.c1 = c1;
|
||||
this.c2 = c2;
|
||||
this.expected = expected;
|
||||
|
||||
// verify prerequisite
|
||||
Stream<Integer> s1s = c1.stream();
|
||||
Stream<Integer> s2s = c2.stream();
|
||||
Stream<Integer> s1p = c1.parallelStream();
|
||||
Stream<Integer> s2p = c2.parallelStream();
|
||||
assertTrue(s1p.isParallel());
|
||||
assertTrue(s2p.isParallel());
|
||||
assertFalse(s1s.isParallel());
|
||||
assertFalse(s2s.isParallel());
|
||||
|
||||
assertTrue(s1s.spliterator().hasCharacteristics(Spliterator.ORDERED));
|
||||
assertTrue(s1p.spliterator().hasCharacteristics(Spliterator.ORDERED));
|
||||
assertTrue(s2s.spliterator().hasCharacteristics(Spliterator.ORDERED));
|
||||
assertTrue(s2p.spliterator().hasCharacteristics(Spliterator.ORDERED));
|
||||
}
|
||||
|
||||
private <T> void assertConcatContent(Spliterator<T> sp, boolean ordered, Spliterator<T> expected) {
|
||||
// concat stream cannot guarantee uniqueness
|
||||
assertFalse(sp.hasCharacteristics(Spliterator.DISTINCT), scenario);
|
||||
// concat stream cannot guarantee sorted
|
||||
assertFalse(sp.hasCharacteristics(Spliterator.SORTED), scenario);
|
||||
// concat stream is ordered if both are ordered
|
||||
assertEquals(sp.hasCharacteristics(Spliterator.ORDERED), ordered, scenario);
|
||||
|
||||
// Verify elements
|
||||
if (ordered) {
|
||||
assertEquals(toBoxedList(sp),
|
||||
toBoxedList(expected),
|
||||
scenario);
|
||||
} else {
|
||||
assertEquals(toBoxedMultiset(sp),
|
||||
toBoxedMultiset(expected),
|
||||
scenario);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertRefConcat(Stream<Integer> s1, Stream<Integer> s2, boolean parallel, boolean ordered) {
|
||||
Stream<Integer> result = Stream.concat(s1, s2);
|
||||
assertEquals(result.isParallel(), parallel);
|
||||
assertConcatContent(result.spliterator(), ordered, expected.spliterator());
|
||||
}
|
||||
|
||||
private void assertIntConcat(Stream<Integer> s1, Stream<Integer> s2, boolean parallel, boolean ordered) {
|
||||
IntStream result = IntStream.concat(s1.mapToInt(Integer::intValue),
|
||||
s2.mapToInt(Integer::intValue));
|
||||
assertEquals(result.isParallel(), parallel);
|
||||
assertConcatContent(result.spliterator(), ordered,
|
||||
expected.stream().mapToInt(Integer::intValue).spliterator());
|
||||
}
|
||||
|
||||
private void assertLongConcat(Stream<Integer> s1, Stream<Integer> s2, boolean parallel, boolean ordered) {
|
||||
LongStream result = LongStream.concat(s1.mapToLong(Integer::longValue),
|
||||
s2.mapToLong(Integer::longValue));
|
||||
assertEquals(result.isParallel(), parallel);
|
||||
assertConcatContent(result.spliterator(), ordered,
|
||||
expected.stream().mapToLong(Integer::longValue).spliterator());
|
||||
}
|
||||
|
||||
private void assertDoubleConcat(Stream<Integer> s1, Stream<Integer> s2, boolean parallel, boolean ordered) {
|
||||
DoubleStream result = DoubleStream.concat(s1.mapToDouble(Integer::doubleValue),
|
||||
s2.mapToDouble(Integer::doubleValue));
|
||||
assertEquals(result.isParallel(), parallel);
|
||||
assertConcatContent(result.spliterator(), ordered,
|
||||
expected.stream().mapToDouble(Integer::doubleValue).spliterator());
|
||||
}
|
||||
|
||||
public void testRefConcat() {
|
||||
// sequential + sequential -> sequential
|
||||
assertRefConcat(c1.stream(), c2.stream(), false, true);
|
||||
// parallel + parallel -> parallel
|
||||
assertRefConcat(c1.parallelStream(), c2.parallelStream(), true, true);
|
||||
// sequential + parallel -> parallel
|
||||
assertRefConcat(c1.stream(), c2.parallelStream(), true, true);
|
||||
// parallel + sequential -> parallel
|
||||
assertRefConcat(c1.parallelStream(), c2.stream(), true, true);
|
||||
|
||||
// not ordered
|
||||
assertRefConcat(c1.stream().unordered(), c2.stream(), false, false);
|
||||
assertRefConcat(c1.stream(), c2.stream().unordered(), false, false);
|
||||
assertRefConcat(c1.parallelStream().unordered(), c2.stream().unordered(), true, false);
|
||||
}
|
||||
|
||||
public void testIntConcat() {
|
||||
// sequential + sequential -> sequential
|
||||
assertIntConcat(c1.stream(), c2.stream(), false, true);
|
||||
// parallel + parallel -> parallel
|
||||
assertIntConcat(c1.parallelStream(), c2.parallelStream(), true, true);
|
||||
// sequential + parallel -> parallel
|
||||
assertIntConcat(c1.stream(), c2.parallelStream(), true, true);
|
||||
// parallel + sequential -> parallel
|
||||
assertIntConcat(c1.parallelStream(), c2.stream(), true, true);
|
||||
|
||||
// not ordered
|
||||
assertIntConcat(c1.stream().unordered(), c2.stream(), false, false);
|
||||
assertIntConcat(c1.stream(), c2.stream().unordered(), false, false);
|
||||
assertIntConcat(c1.parallelStream().unordered(), c2.stream().unordered(), true, false);
|
||||
}
|
||||
|
||||
public void testLongConcat() {
|
||||
// sequential + sequential -> sequential
|
||||
assertLongConcat(c1.stream(), c2.stream(), false, true);
|
||||
// parallel + parallel -> parallel
|
||||
assertLongConcat(c1.parallelStream(), c2.parallelStream(), true, true);
|
||||
// sequential + parallel -> parallel
|
||||
assertLongConcat(c1.stream(), c2.parallelStream(), true, true);
|
||||
// parallel + sequential -> parallel
|
||||
assertLongConcat(c1.parallelStream(), c2.stream(), true, true);
|
||||
|
||||
// not ordered
|
||||
assertLongConcat(c1.stream().unordered(), c2.stream(), false, false);
|
||||
assertLongConcat(c1.stream(), c2.stream().unordered(), false, false);
|
||||
assertLongConcat(c1.parallelStream().unordered(), c2.stream().unordered(), true, false);
|
||||
}
|
||||
|
||||
public void testDoubleConcat() {
|
||||
// sequential + sequential -> sequential
|
||||
assertDoubleConcat(c1.stream(), c2.stream(), false, true);
|
||||
// parallel + parallel -> parallel
|
||||
assertDoubleConcat(c1.parallelStream(), c2.parallelStream(), true, true);
|
||||
// sequential + parallel -> parallel
|
||||
assertDoubleConcat(c1.stream(), c2.parallelStream(), true, true);
|
||||
// parallel + sequential -> parallel
|
||||
assertDoubleConcat(c1.parallelStream(), c2.stream(), true, true);
|
||||
|
||||
// not ordered
|
||||
assertDoubleConcat(c1.stream().unordered(), c2.stream(), false, false);
|
||||
assertDoubleConcat(c1.stream(), c2.stream().unordered(), false, false);
|
||||
assertDoubleConcat(c1.parallelStream().unordered(), c2.stream().unordered(), true, false);
|
||||
}
|
||||
}
|
@ -226,116 +226,114 @@ public class RangeTest extends OpTestCase {
|
||||
assertEquals(first, LongStream.iterate(0, i -> i + 1).parallel().filter(i -> i > 10000).findFirst().getAsLong());
|
||||
}
|
||||
|
||||
// Enable when Stream.concat is present and range implementations are
|
||||
// updated to use that
|
||||
// private static void assertSizedAndSubSized(Spliterator<?> s) {
|
||||
// assertTrue(s.hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED));
|
||||
// }
|
||||
//
|
||||
// private static void assertNotSizedAndSubSized(Spliterator<?> s) {
|
||||
// assertFalse(s.hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED));
|
||||
// }
|
||||
//
|
||||
// public void testLongLongRange() {
|
||||
// // Test [Long.MIN_VALUE, Long.MAX_VALUE)
|
||||
// // This will concatenate streams of three ranges
|
||||
// // [Long.MIN_VALUE, x) [x, 0) [0, Long.MAX_VALUE)
|
||||
// // where x = Long.divideUnsigned(0 - Long.MIN_VALUE, 2) + 1
|
||||
// {
|
||||
// Spliterator.OfLong s = LongStream.range(Long.MIN_VALUE, Long.MAX_VALUE).spliterator();
|
||||
//
|
||||
// assertEquals(s.estimateSize(), Long.MAX_VALUE);
|
||||
// assertNotSizedAndSubSized(s);
|
||||
//
|
||||
// Spliterator.OfLong s1 = s.trySplit();
|
||||
// assertNotSizedAndSubSized(s1);
|
||||
// assertSizedAndSubSized(s);
|
||||
//
|
||||
// Spliterator.OfLong s2 = s1.trySplit();
|
||||
// assertSizedAndSubSized(s1);
|
||||
// assertSizedAndSubSized(s2);
|
||||
//
|
||||
// assertTrue(s.estimateSize() == Long.MAX_VALUE);
|
||||
// assertTrue(s1.estimateSize() < Long.MAX_VALUE);
|
||||
// assertTrue(s2.estimateSize() < Long.MAX_VALUE);
|
||||
//
|
||||
// assertEquals(s.estimateSize() + s1.estimateSize() + s2.estimateSize(),
|
||||
// Long.MAX_VALUE - Long.MIN_VALUE);
|
||||
// }
|
||||
//
|
||||
// long[][] ranges = { {Long.MIN_VALUE, 0}, {-1, Long.MAX_VALUE} };
|
||||
// for (int i = 0; i < ranges.length; i++) {
|
||||
// long start = ranges[i][0];
|
||||
// long end = ranges[i][1];
|
||||
//
|
||||
// Spliterator.OfLong s = LongStream.range(start, end).spliterator();
|
||||
//
|
||||
// assertEquals(s.estimateSize(), Long.MAX_VALUE);
|
||||
// assertNotSizedAndSubSized(s);
|
||||
//
|
||||
// Spliterator.OfLong s1 = s.trySplit();
|
||||
// assertSizedAndSubSized(s1);
|
||||
// assertSizedAndSubSized(s);
|
||||
//
|
||||
// assertTrue(s.estimateSize() < Long.MAX_VALUE);
|
||||
// assertTrue(s1.estimateSize() < Long.MAX_VALUE);
|
||||
//
|
||||
// assertEquals(s.estimateSize() + s1.estimateSize(), end - start);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void testLongLongRangeClosed() {
|
||||
// // Test [Long.MIN_VALUE, Long.MAX_VALUE]
|
||||
// // This will concatenate streams of four ranges
|
||||
// // [Long.MIN_VALUE, x) [x, 0) [0, y) [y, Long.MAX_VALUE]
|
||||
// // where x = Long.divideUnsigned(0 - Long.MIN_VALUE, 2) + 1
|
||||
// // y = Long.divideUnsigned(Long.MAX_VALUE, 2) + 1
|
||||
//
|
||||
// {
|
||||
// Spliterator.OfLong s = LongStream.rangeClosed(Long.MIN_VALUE, Long.MAX_VALUE).spliterator();
|
||||
//
|
||||
// assertEquals(s.estimateSize(), Long.MAX_VALUE);
|
||||
// assertNotSizedAndSubSized(s);
|
||||
//
|
||||
// Spliterator.OfLong s1 = s.trySplit();
|
||||
// assertNotSizedAndSubSized(s1);
|
||||
// assertNotSizedAndSubSized(s);
|
||||
//
|
||||
// Spliterator.OfLong s2 = s1.trySplit();
|
||||
// assertSizedAndSubSized(s1);
|
||||
// assertSizedAndSubSized(s2);
|
||||
//
|
||||
// Spliterator.OfLong s3 = s.trySplit();
|
||||
// assertSizedAndSubSized(s3);
|
||||
// assertSizedAndSubSized(s);
|
||||
//
|
||||
// assertTrue(s.estimateSize() < Long.MAX_VALUE);
|
||||
// assertTrue(s3.estimateSize() < Long.MAX_VALUE);
|
||||
// assertTrue(s1.estimateSize() < Long.MAX_VALUE);
|
||||
// assertTrue(s2.estimateSize() < Long.MAX_VALUE);
|
||||
//
|
||||
// assertEquals(s.estimateSize() + s3.estimateSize() + s1.estimateSize() + s2.estimateSize(),
|
||||
// Long.MAX_VALUE - Long.MIN_VALUE + 1);
|
||||
// }
|
||||
//
|
||||
// long[][] ranges = { {Long.MIN_VALUE, 0}, {-1, Long.MAX_VALUE} };
|
||||
// for (int i = 0; i < ranges.length; i++) {
|
||||
// long start = ranges[i][0];
|
||||
// long end = ranges[i][1];
|
||||
//
|
||||
// Spliterator.OfLong s = LongStream.rangeClosed(start, end).spliterator();
|
||||
//
|
||||
// assertEquals(s.estimateSize(), Long.MAX_VALUE);
|
||||
// assertNotSizedAndSubSized(s);
|
||||
//
|
||||
// Spliterator.OfLong s1 = s.trySplit();
|
||||
// assertSizedAndSubSized(s1);
|
||||
// assertSizedAndSubSized(s);
|
||||
//
|
||||
// assertTrue(s.estimateSize() < Long.MAX_VALUE);
|
||||
// assertTrue(s1.estimateSize() < Long.MAX_VALUE);
|
||||
//
|
||||
// assertEquals(s.estimateSize() + s1.estimateSize(), end - start + 1);
|
||||
// }
|
||||
// }
|
||||
private static void assertSizedAndSubSized(Spliterator<?> s) {
|
||||
assertTrue(s.hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED));
|
||||
}
|
||||
|
||||
private static void assertNotSizedAndSubSized(Spliterator<?> s) {
|
||||
assertFalse(s.hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED));
|
||||
}
|
||||
|
||||
public void testLongLongRange() {
|
||||
// Test [Long.MIN_VALUE, Long.MAX_VALUE)
|
||||
// This will concatenate streams of three ranges
|
||||
// [Long.MIN_VALUE, x) [x, 0) [0, Long.MAX_VALUE)
|
||||
// where x = Long.divideUnsigned(0 - Long.MIN_VALUE, 2) + 1
|
||||
{
|
||||
Spliterator.OfLong s = LongStream.range(Long.MIN_VALUE, Long.MAX_VALUE).spliterator();
|
||||
|
||||
assertEquals(s.estimateSize(), Long.MAX_VALUE);
|
||||
assertNotSizedAndSubSized(s);
|
||||
|
||||
Spliterator.OfLong s1 = s.trySplit();
|
||||
assertNotSizedAndSubSized(s1);
|
||||
assertSizedAndSubSized(s);
|
||||
|
||||
Spliterator.OfLong s2 = s1.trySplit();
|
||||
assertSizedAndSubSized(s1);
|
||||
assertSizedAndSubSized(s2);
|
||||
|
||||
assertTrue(s.estimateSize() == Long.MAX_VALUE);
|
||||
assertTrue(s1.estimateSize() < Long.MAX_VALUE);
|
||||
assertTrue(s2.estimateSize() < Long.MAX_VALUE);
|
||||
|
||||
assertEquals(s.estimateSize() + s1.estimateSize() + s2.estimateSize(),
|
||||
Long.MAX_VALUE - Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
long[][] ranges = { {Long.MIN_VALUE, 0}, {-1, Long.MAX_VALUE} };
|
||||
for (int i = 0; i < ranges.length; i++) {
|
||||
long start = ranges[i][0];
|
||||
long end = ranges[i][1];
|
||||
|
||||
Spliterator.OfLong s = LongStream.range(start, end).spliterator();
|
||||
|
||||
assertEquals(s.estimateSize(), Long.MAX_VALUE);
|
||||
assertNotSizedAndSubSized(s);
|
||||
|
||||
Spliterator.OfLong s1 = s.trySplit();
|
||||
assertSizedAndSubSized(s1);
|
||||
assertSizedAndSubSized(s);
|
||||
|
||||
assertTrue(s.estimateSize() < Long.MAX_VALUE);
|
||||
assertTrue(s1.estimateSize() < Long.MAX_VALUE);
|
||||
|
||||
assertEquals(s.estimateSize() + s1.estimateSize(), end - start);
|
||||
}
|
||||
}
|
||||
|
||||
public void testLongLongRangeClosed() {
|
||||
// Test [Long.MIN_VALUE, Long.MAX_VALUE]
|
||||
// This will concatenate streams of four ranges
|
||||
// [Long.MIN_VALUE, x) [x, 0) [0, y) [y, Long.MAX_VALUE]
|
||||
// where x = Long.divideUnsigned(0 - Long.MIN_VALUE, 2) + 1
|
||||
// y = Long.divideUnsigned(Long.MAX_VALUE, 2) + 1
|
||||
|
||||
{
|
||||
Spliterator.OfLong s = LongStream.rangeClosed(Long.MIN_VALUE, Long.MAX_VALUE).spliterator();
|
||||
|
||||
assertEquals(s.estimateSize(), Long.MAX_VALUE);
|
||||
assertNotSizedAndSubSized(s);
|
||||
|
||||
Spliterator.OfLong s1 = s.trySplit();
|
||||
assertNotSizedAndSubSized(s1);
|
||||
assertNotSizedAndSubSized(s);
|
||||
|
||||
Spliterator.OfLong s2 = s1.trySplit();
|
||||
assertSizedAndSubSized(s1);
|
||||
assertSizedAndSubSized(s2);
|
||||
|
||||
Spliterator.OfLong s3 = s.trySplit();
|
||||
assertSizedAndSubSized(s3);
|
||||
assertSizedAndSubSized(s);
|
||||
|
||||
assertTrue(s.estimateSize() < Long.MAX_VALUE);
|
||||
assertTrue(s3.estimateSize() < Long.MAX_VALUE);
|
||||
assertTrue(s1.estimateSize() < Long.MAX_VALUE);
|
||||
assertTrue(s2.estimateSize() < Long.MAX_VALUE);
|
||||
|
||||
assertEquals(s.estimateSize() + s3.estimateSize() + s1.estimateSize() + s2.estimateSize(),
|
||||
Long.MAX_VALUE - Long.MIN_VALUE + 1);
|
||||
}
|
||||
|
||||
long[][] ranges = { {Long.MIN_VALUE, 0}, {-1, Long.MAX_VALUE} };
|
||||
for (int i = 0; i < ranges.length; i++) {
|
||||
long start = ranges[i][0];
|
||||
long end = ranges[i][1];
|
||||
|
||||
Spliterator.OfLong s = LongStream.rangeClosed(start, end).spliterator();
|
||||
|
||||
assertEquals(s.estimateSize(), Long.MAX_VALUE);
|
||||
assertNotSizedAndSubSized(s);
|
||||
|
||||
Spliterator.OfLong s1 = s.trySplit();
|
||||
assertSizedAndSubSized(s1);
|
||||
assertSizedAndSubSized(s);
|
||||
|
||||
assertTrue(s.estimateSize() < Long.MAX_VALUE);
|
||||
assertTrue(s1.estimateSize() < Long.MAX_VALUE);
|
||||
|
||||
assertEquals(s.estimateSize() + s1.estimateSize(), end - start + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user