提交 d7ce324e 编写于 作者: A alanb

Merge

......@@ -759,12 +759,13 @@ public interface IntStream extends BaseStream<Integer, IntStream> {
/**
* Returns a sequential {@code IntStream} from {@code startInclusive}
* (inclusive) to {@code endExclusive} (exclusive) by an incremental step of
* 1.
* {@code 1}.
*
* @implSpec
* The implementation behaves as if:
* @apiNote
* <p>An equivalent sequence of increasing values can be produced
* sequentially using a {@code for} loop as follows:
* <pre>{@code
* intRange(startInclusive, endExclusive, 1);
* for (int i = startInclusive; i < endExclusive ; i++) { ... }
* }</pre>
*
* @param startInclusive the (inclusive) initial value
......@@ -773,36 +774,37 @@ public interface IntStream extends BaseStream<Integer, IntStream> {
* elements
*/
public static IntStream range(int startInclusive, int endExclusive) {
return range(startInclusive, endExclusive, 1);
if (startInclusive >= endExclusive) {
return empty();
} else {
return StreamSupport.intStream(
new Streams.RangeIntSpliterator(startInclusive, endExclusive, false));
}
}
/**
* Returns a sequential {@code IntStream} from {@code startInclusive}
* (inclusive) to {@code endExclusive} (exclusive) by a positive {@code
* step}. If {@code startInclusive} is greater than or equal to {@code
* endExclusive}, an empty stream is returned.
* (inclusive) to {@code endInclusive} (inclusive) by an incremental step of
* {@code 1}.
*
* @apiNote
* <p>An equivalent sequence of increasing values can be produced
* sequentially using a {@code for} loop as follows:
* <pre>{@code
* for (int i = startInclusive; i < endExclusive ; i += step) { ... }
* for (int i = startInclusive; i <= endInclusive ; i++) { ... }
* }</pre>
*
* @param startInclusive the (inclusive) initial value
* @param endExclusive the exclusive upper bound
* @param step the positive difference between consecutive values
* @param endInclusive the inclusive upper bound
* @return a sequential {@code IntStream} for the range of {@code int}
* elements
* @throws IllegalArgumentException if {@code step} is less than or equal to
* 0
*/
public static IntStream range(int startInclusive, int endExclusive, int step) {
if (step <= 0) {
throw new IllegalArgumentException(String.format("Illegal step: %d", step));
} else if (startInclusive >= endExclusive) {
public static IntStream rangeClosed(int startInclusive, int endInclusive) {
if (startInclusive > endInclusive) {
return empty();
} else {
return StreamSupport.intStream(new Streams.RangeIntSpliterator(startInclusive, endExclusive, step));
return StreamSupport.intStream(
new Streams.RangeIntSpliterator(startInclusive, endInclusive, true));
}
}
}
......@@ -750,12 +750,13 @@ public interface LongStream extends BaseStream<Long, LongStream> {
/**
* Returns a sequential {@code LongStream} from {@code startInclusive}
* (inclusive) to {@code endExclusive} (exclusive) by an incremental step of
* 1.
* {@code 1}.
*
* @implSpec
* The implementation behaves as if:
* @apiNote
* <p>An equivalent sequence of increasing values can be produced
* sequentially using a {@code for} loop as follows:
* <pre>{@code
* longRange(startInclusive, endExclusive, 1);
* for (long i = startInclusive; i < endExclusive ; i++) { ... }
* }</pre>
*
* @param startInclusive the (inclusive) initial value
......@@ -764,36 +765,56 @@ public interface LongStream extends BaseStream<Long, LongStream> {
* elements
*/
public static LongStream range(long startInclusive, final long endExclusive) {
return range(startInclusive, endExclusive, 1);
if (startInclusive >= endExclusive) {
return empty();
} else if (endExclusive - startInclusive < 0) {
// Size of range > Long.MAX_VALUE
// 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();
} else {
return StreamSupport.longStream(
new Streams.RangeLongSpliterator(startInclusive, endExclusive, false));
}
}
/**
* Returns a sequential {@code LongStream} from {@code startInclusive}
* (inclusive) to {@code endExclusive} (exclusive) by {@code step}. If
* {@code startInclusive} is greater than or equal to {@code
* endExclusive}, an empty stream is returned.
* (inclusive) to {@code endInclusive} (inclusive) by an incremental step of
* {@code 1}.
*
* @apiNote
* <p>An equivalent sequence of increasing values can be produced
* sequentially using a {@code for} loop as follows:
* <pre>{@code
* for (long i = startInclusive; i < endExclusive ; i += step) { ... }
* for (long i = startInclusive; i <= endInclusive ; i++) { ... }
* }</pre>
*
* @param startInclusive the (inclusive) initial value
* @param endExclusive the exclusive upper bound
* @param step the difference between consecutive values
* @param endInclusive the inclusive upper bound
* @return a sequential {@code LongStream} for the range of {@code long}
* elements
* @throws IllegalArgumentException if {@code step} is less than or equal to
* 0
*/
public static LongStream range(long startInclusive, final long endExclusive, final long step) {
if (step <= 0) {
throw new IllegalArgumentException(String.format("Illegal step: %d", step));
} else if (startInclusive >= endExclusive) {
public static LongStream rangeClosed(long startInclusive, final long endInclusive) {
if (startInclusive > endInclusive) {
return empty();
} else if (endInclusive - startInclusive + 1 <= 0) {
// Size of range > Long.MAX_VALUE
// 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), 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();
} else {
return StreamSupport.longStream(new Streams.RangeLongSpliterator(startInclusive, endExclusive, step));
return StreamSupport.longStream(
new Streams.RangeLongSpliterator(startInclusive, endInclusive, true));
}
}
}
......@@ -25,7 +25,6 @@
package java.util.stream;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
......@@ -62,39 +61,62 @@ class Streams {
* An {@code int} range spliterator.
*/
static final class RangeIntSpliterator implements Spliterator.OfInt {
// Can never be greater that upTo, this avoids overflow if upper bound
// is Integer.MAX_VALUE
// All elements are traversed if from == upTo & last == 0
private int from;
private final int upTo;
private final int step;
// 1 if the range is closed and the last element has not been traversed
// Otherwise, 0 if the range is open, or is a closed range and all
// elements have been traversed
private int last;
RangeIntSpliterator(int from, int upTo, int step) {
RangeIntSpliterator(int from, int upTo, boolean closed) {
this(from, upTo, closed ? 1 : 0);
}
private RangeIntSpliterator(int from, int upTo, int last) {
this.from = from;
this.upTo = upTo;
this.step = step;
this.last = last;
}
@Override
public boolean tryAdvance(IntConsumer consumer) {
boolean hasNext = from < upTo;
if (hasNext) {
consumer.accept(from);
from += step;
final int i = from;
if (i < upTo) {
from++;
consumer.accept(i);
return true;
}
else if (last > 0) {
last = 0;
consumer.accept(i);
return true;
}
return hasNext;
return false;
}
@Override
public void forEachRemaining(IntConsumer consumer) {
int hUpTo = upTo;
int hStep = step; // hoist accesses and checks from loop
for (int i = from; i < hUpTo; i += hStep)
consumer.accept(i);
int i = from;
final int hUpTo = upTo;
int hLast = last;
from = upTo;
last = 0;
while (i < hUpTo) {
consumer.accept(i++);
}
if (hLast > 0) {
// Last element of closed range
consumer.accept(i);
}
}
@Override
public long estimateSize() {
int d = upTo - from;
return (d / step) + ((d % step == 0) ? 0 : 1);
// Ensure ranges of size > Integer.MAX_VALUE report the correct size
return ((long) upTo) - from + last;
}
@Override
......@@ -111,57 +133,108 @@ class Streams {
@Override
public Spliterator.OfInt trySplit() {
return estimateSize() <= 1
long size = estimateSize();
return size <= 1
? null
: new RangeIntSpliterator(from, from = from + midPoint(), step);
// Left split always has a half-open range
: new RangeIntSpliterator(from, from = from + splitPoint(size), 0);
}
private int midPoint() {
// Size is known to be >= 2
int bisection = (upTo - from) / 2;
// If bisection > step then round down to nearest multiple of step
// otherwise round up to step
return bisection > step ? bisection - bisection % step : step;
/**
* The spliterator size below which the spliterator will be split
* at the mid-point to produce balanced splits. Above this size the
* spliterator will be split at a ratio of
* 1:(RIGHT_BALANCED_SPLIT_RATIO - 1)
* to produce right-balanced splits.
*
* <p>Such splitting ensures that for very large ranges that the left
* side of the range will more likely be processed at a lower-depth
* than a balanced tree at the expense of a higher-depth for the right
* side of the range.
*
* <p>This is optimized for cases such as IntStream.ints() that is
* implemented as range of 0 to Integer.MAX_VALUE but is likely to be
* augmented with a limit operation that limits the number of elements
* to a count lower than this threshold.
*/
private static final int BALANCED_SPLIT_THRESHOLD = 1 << 24;
/**
* The split ratio of the left and right split when the spliterator
* size is above BALANCED_SPLIT_THRESHOLD.
*/
private static final int RIGHT_BALANCED_SPLIT_RATIO = 1 << 3;
private int splitPoint(long size) {
int d = (size < BALANCED_SPLIT_THRESHOLD) ? 2 : RIGHT_BALANCED_SPLIT_RATIO;
// 2 <= size <= 2^32
return (int) (size / d);
}
}
/**
* A {@code long} range spliterator.
*
* This implementation cannot be used for ranges whose size is greater
* than Long.MAX_VALUE
*/
static final class RangeLongSpliterator implements Spliterator.OfLong {
// Can never be greater that upTo, this avoids overflow if upper bound
// is Long.MAX_VALUE
// All elements are traversed if from == upTo & last == 0
private long from;
private final long upTo;
private final long step;
// 1 if the range is closed and the last element has not been traversed
// Otherwise, 0 if the range is open, or is a closed range and all
// elements have been traversed
private int last;
RangeLongSpliterator(long from, long upTo, long step) {
RangeLongSpliterator(long from, long upTo, boolean closed) {
this(from, upTo, closed ? 1 : 0);
}
private RangeLongSpliterator(long from, long upTo, int last) {
assert upTo - from + last > 0;
this.from = from;
this.upTo = upTo;
this.step = step;
this.last = last;
}
@Override
public boolean tryAdvance(LongConsumer consumer) {
boolean hasNext = from < upTo;
if (hasNext) {
consumer.accept(from);
from += step;
final long i = from;
if (i < upTo) {
from++;
consumer.accept(i);
return true;
}
else if (last > 0) {
last = 0;
consumer.accept(i);
return true;
}
return hasNext;
return false;
}
@Override
public void forEachRemaining(LongConsumer consumer) {
long hUpTo = upTo;
long hStep = step; // hoist accesses and checks from loop
for (long i = from; i < hUpTo; i += hStep)
consumer.accept(i);
long i = from;
final long hUpTo = upTo;
int hLast = last;
from = upTo;
last = 0;
while (i < hUpTo) {
consumer.accept(i++);
}
if (hLast > 0) {
// Last element of closed range
consumer.accept(i);
}
}
@Override
public long estimateSize() {
long d = upTo - from;
return (d / step) + ((d % step == 0) ? 0 : 1);
return upTo - from + last;
}
@Override
......@@ -178,17 +251,42 @@ class Streams {
@Override
public Spliterator.OfLong trySplit() {
return estimateSize() <= 1
long size = estimateSize();
return size <= 1
? null
: new RangeLongSpliterator(from, from = from + midPoint(), step);
// Left split always has a half-open range
: new RangeLongSpliterator(from, from = from + splitPoint(size), 0);
}
private long midPoint() {
// Size is known to be >= 2
long bisection = (upTo - from) / 2;
// If bisection > step then round down to nearest multiple of step
// otherwise round up to step
return bisection > step ? bisection - bisection % step : step;
/**
* The spliterator size below which the spliterator will be split
* at the mid-point to produce balanced splits. Above this size the
* spliterator will be split at a ratio of
* 1:(RIGHT_BALANCED_SPLIT_RATIO - 1)
* to produce right-balanced splits.
*
* <p>Such splitting ensures that for very large ranges that the left
* side of the range will more likely be processed at a lower-depth
* than a balanced tree at the expense of a higher-depth for the right
* side of the range.
*
* <p>This is optimized for cases such as LongStream.longs() that is
* implemented as range of 0 to Long.MAX_VALUE but is likely to be
* augmented with a limit operation that limits the number of elements
* to a count lower than this threshold.
*/
private static final long BALANCED_SPLIT_THRESHOLD = 1 << 24;
/**
* The split ratio of the left and right split when the spliterator
* size is above BALANCED_SPLIT_THRESHOLD.
*/
private static final long RIGHT_BALANCED_SPLIT_RATIO = 1 << 3;
private long splitPoint(long size) {
long d = (size < BALANCED_SPLIT_THRESHOLD) ? 2 : RIGHT_BALANCED_SPLIT_RATIO;
// 2 <= size <= Long.MAX_VALUE
return size / d;
}
}
......
......@@ -95,12 +95,8 @@ public class IntStreamTestDataProvider {
list.add(streamDataDescr("IntStream.intRange(0,l): " + ints.length,
() -> IntStream.range(0, ints.length)));
list.add(streamDataDescr("IntStream.intRange(0,l,2): " + ints.length,
() -> IntStream.range(0, ints.length, 2)));
list.add(streamDataDescr("IntStream.intRange(0,l,3): " + ints.length,
() -> IntStream.range(0, ints.length, 3)));
list.add(streamDataDescr("IntStream.intRange(0,l,7): " + ints.length,
() -> IntStream.range(0, ints.length, 7)));
list.add(streamDataDescr("IntStream.rangeClosed(0,l): " + ints.length,
() -> IntStream.rangeClosed(0, ints.length)));
}
testData = list.toArray(new Object[0][]);
}
......@@ -131,12 +127,8 @@ public class IntStreamTestDataProvider {
spliterators.add(splitDescr("IntStream.intRange(0,l):" + name,
() -> IntStream.range(0, ints.length).spliterator()));
spliterators.add(splitDescr("IntStream.intRange(0,l,2):" + name,
() -> IntStream.range(0, ints.length, 2).spliterator()));
spliterators.add(splitDescr("IntStream.intRange(0,l,3):" + name,
() -> IntStream.range(0, ints.length, 3).spliterator()));
spliterators.add(splitDescr("IntStream.intRange(0,l,7):" + name,
() -> IntStream.range(0, ints.length, 7).spliterator()));
spliterators.add(splitDescr("IntStream.intRangeClosed(0,l):" + name,
() -> IntStream.rangeClosed(0, ints.length).spliterator()));
// Need more!
}
......
......@@ -95,12 +95,8 @@ public class LongStreamTestDataProvider {
list.add(streamDataDescr("LongStream.longRange(0,l): " + longs.length,
() -> LongStream.range(0, longs.length)));
list.add(streamDataDescr("LongStream.longRange(0,l,2): " + longs.length,
() -> LongStream.range(0, longs.length, 2)));
list.add(streamDataDescr("LongStream.longRange(0,l,3): " + longs.length,
() -> LongStream.range(0, longs.length, 3)));
list.add(streamDataDescr("LongStream.longRange(0,l,7): " + longs.length,
() -> LongStream.range(0, longs.length, 7)));
list.add(streamDataDescr("LongStream.longRangeClosed(0,l): " + longs.length,
() -> LongStream.rangeClosed(0, longs.length)));
}
testData = list.toArray(new Object[0][]);
}
......@@ -131,12 +127,8 @@ public class LongStreamTestDataProvider {
spliterators.add(splitDescr("LongStream.longRange(0,l):" + name,
() -> LongStream.range(0, longs.length).spliterator()));
spliterators.add(splitDescr("LongStream.longRange(0,l,2):" + name,
() -> LongStream.range(0, longs.length, 2).spliterator()));
spliterators.add(splitDescr("LongStream.longRange(0,l,3):" + name,
() -> LongStream.range(0, longs.length, 3).spliterator()));
spliterators.add(splitDescr("LongStream.longRange(0,l,7):" + name,
() -> LongStream.range(0, longs.length, 7).spliterator()));
spliterators.add(splitDescr("LongStream.longRangeClosed(0,l):" + name,
() -> LongStream.rangeClosed(0, longs.length).spliterator()));
// Need more!
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
......
......@@ -24,10 +24,11 @@ package org.openjdk.tests.java.util.stream;
import java.util.Arrays;
import java.util.Optional;
import java.util.stream.DoubleStream;
import java.util.Spliterator;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.OpTestCase;
import java.util.stream.SpliteratorTestHelper;
import java.util.stream.Stream;
import java.util.stream.TestData;
......@@ -54,73 +55,76 @@ public class RangeTest extends OpTestCase {
//
public void testIntRangeErrors() {
for (int start : Arrays.asList(1, 10, -1, -10)) {
for (int end : Arrays.asList(1, 10, -1, -10)) {
for (int step : Arrays.asList(0, 1, -1, Integer.MAX_VALUE, Integer.MIN_VALUE)) {
if (step > 0)
executeAndNoCatch(() -> IntStream.range(start, end, step));
else
executeAndCatch(() -> IntStream.range(start, end, step));
}
}
}
}
public void testIntRange() {
// Without step
// Half-open
for (int start : Arrays.asList(1, 10, -1, -10)) {
for (int end : Arrays.asList(1, 10, -1, -10)) {
int step = 1;
int size = (start < end) ? end - start : 0;
int[] exp = new int[size];
if (start < end) {
for (int i = start, p = 0; i < end; i++, p++) {
exp[p] = i;
}
for (int i = start, p = 0; i < end; i++, p++) {
exp[p] = i;
}
int[] inc = IntStream.range(start, end).toArray();
assertEquals(inc.length, size);
assertTrue(Arrays.equals(exp, inc));
withData(intRangeData(start, end, step)).stream(s -> s).
withData(intRangeData(start, end)).stream(s -> s).
expectedResult(exp).exercise();
}
}
// With step
// Closed
for (int start : Arrays.asList(1, 10, -1, -10)) {
for (int end : Arrays.asList(1, 10, -1, -10)) {
for (int step : Arrays.asList(1, -1, -2, 2)) {
if (step > 0) {
int d = end - start;
int size = (start < end) ? (d / step) + ((d % step == 0) ? 0 : 1) : 0;
int[] exp = new int[size];
if (start < end) {
for (int i = start, p = 0; i < end; i += step, p++) {
exp[p] = i;
}
}
int[] inc = IntStream.range(start, end, step).toArray();
assertEquals(inc.length, size);
assertTrue(Arrays.equals(exp, inc));
withData(intRangeData(start, end, step)).stream(s -> s).
expectedResult(exp).exercise();
}
int size = (start <= end) ? end - start + 1 : 0;
int[] exp = new int[size];
for (int i = start, p = 0; i <= end; i++, p++) {
exp[p] = i;
}
int[] inc = IntStream.rangeClosed(start, end).toArray();
assertEquals(inc.length, size);
assertTrue(Arrays.equals(exp, inc));
withData(intRangeClosedData(start, end)).stream(s -> s).
expectedResult(exp).exercise();
}
}
// Closed, maximum upper bound of Integer.MAX_VALUE
{
int[] inc = IntStream.rangeClosed(Integer.MAX_VALUE - 1, Integer.MAX_VALUE).toArray();
assertEquals(2, inc.length);
assertEquals(Integer.MAX_VALUE - 1, inc[0]);
assertEquals(Integer.MAX_VALUE, inc[1]);
inc = IntStream.rangeClosed(Integer.MAX_VALUE, Integer.MAX_VALUE).toArray();
assertEquals(1, inc.length);
assertEquals(Integer.MAX_VALUE, inc[0]);
SpliteratorTestHelper.testIntSpliterator(
() -> IntStream.rangeClosed(Integer.MAX_VALUE - 8, Integer.MAX_VALUE).spliterator());
}
// Range wider than Integer.MAX_VALUE
{
Spliterator.OfInt s = IntStream.rangeClosed(Integer.MIN_VALUE, Integer.MAX_VALUE).
spliterator();
assertEquals(s.estimateSize(), 1L << 32);
}
}
TestData.OfInt intRangeData(int start, int end) {
return TestData.Factory.ofIntSupplier("int range", () -> IntStream.range(start, end));
}
TestData.OfInt intRangeData(int start, int end, int step) {
return TestData.Factory.ofIntSupplier("int range", () -> IntStream.range(start, end, step));
TestData.OfInt intRangeClosedData(int start, int end) {
return TestData.Factory.ofIntSupplier("int rangeClosed", () -> IntStream.rangeClosed(start, end));
}
public void tesIntRangeReduce() {
withData(intRangeData(0, 10000, 1)).
withData(intRangeData(0, 10000)).
terminal(s -> s.reduce(0, Integer::sum)).exercise();
}
......@@ -137,74 +141,69 @@ public class RangeTest extends OpTestCase {
//
public void testLongRangeErrors() {
for (long start : Arrays.asList(1, 10, -1, -10)) {
for (long end : Arrays.asList(1, 10, -1, -10)) {
for (long step : Arrays.asList(0L, 1L, -1L, Long.MAX_VALUE, Long.MIN_VALUE)) {
if (step > 0)
executeAndNoCatch(() -> LongStream.range(start, end, step));
else
executeAndCatch(() -> LongStream.range(start, end, step));
}
}
}
}
public void testLongRange() {
// Without step
// Half-open
for (long start : Arrays.asList(1, 1000, -1, -1000)) {
for (long end : Arrays.asList(1, 1000, -1, -1000)) {
long step = 1;
long size = start < end ? end - start : 0;
long[] exp = new long[(int) size];
if (start < end) {
for (long i = start, p = 0; i < end; i++, p++) {
exp[(int) p] = i;
}
for (long i = start, p = 0; i < end; i++, p++) {
exp[(int) p] = i;
}
long[] inc = LongStream.range(start, end).toArray();
assertEquals(inc.length, size);
assertTrue(Arrays.equals(exp, inc));
withData(longRangeData(start, end, step)).stream(s -> s).
withData(longRangeData(start, end)).stream(s -> s).
expectedResult(exp).exercise();
}
}
// With step
// Closed
for (long start : Arrays.asList(1, 1000, -1, -1000)) {
for (long end : Arrays.asList(1, 1000, -1, -1000)) {
for (long step : Arrays.asList(1, -1, -2, 2)) {
if (step > 0) {
long d = end - start;
long size = start < end ? (d / step) + ((d % step == 0) ? 0 : 1) : 0;
long[] exp = new long[(int) size];
if (start < end) {
for (long i = start, p = 0; i < end; i += step, p++) {
exp[(int) p] = i;
}
}
long[] inc = LongStream.range(start, end, step).toArray();
assertEquals(inc.length, size);
assertTrue(Arrays.equals(exp, inc));
withData(longRangeData(start, end, step)).stream(s -> s).
expectedResult(exp).exercise();
}
long size = start <= end ? end - start + 1: 0;
long[] exp = new long[(int) size];
for (long i = start, p = 0; i <= end; i++, p++) {
exp[(int) p] = i;
}
long[] inc = LongStream.rangeClosed(start, end).toArray();
assertEquals(inc.length, size);
assertTrue(Arrays.equals(exp, inc));
withData(longRangeClosedData(start, end)).stream(s -> s).
expectedResult(exp).exercise();
}
}
// Closed, maximum upper bound of Long.MAX_VALUE
{
long[] inc = LongStream.rangeClosed(Long.MAX_VALUE - 1, Long.MAX_VALUE).toArray();
assertEquals(2, inc.length);
assertEquals(Long.MAX_VALUE - 1, inc[0]);
assertEquals(Long.MAX_VALUE, inc[1]);
inc = LongStream.rangeClosed(Long.MAX_VALUE, Long.MAX_VALUE).toArray();
assertEquals(1, inc.length);
assertEquals(Long.MAX_VALUE, inc[0]);
SpliteratorTestHelper.testLongSpliterator(
() -> LongStream.rangeClosed(Long.MAX_VALUE - 8, Long.MAX_VALUE).spliterator());
}
}
TestData.OfLong longRangeData(long start, long end) {
return TestData.Factory.ofLongSupplier("long range", () -> LongStream.range(start, end));
}
TestData.OfLong longRangeData(long start, long end, long step) {
return TestData.Factory.ofLongSupplier("long range", () -> LongStream.range(start, end, step));
TestData.OfLong longRangeClosedData(long start, long end) {
return TestData.Factory.ofLongSupplier("long rangeClosed", () -> LongStream.rangeClosed(start, end));
}
public void testLongRangeReduce() {
withData(longRangeData(0, 10000, 1)).
withData(longRangeData(0, 10000)).
terminal(s -> s.reduce(0, Long::sum)).exercise();
}
......@@ -219,64 +218,116 @@ public class RangeTest extends OpTestCase {
assertEquals(first, LongStream.iterate(0, i -> i + 1).parallel().filter(i -> i > 10000).findFirst().getAsLong());
}
//
private static int[] reverse(int[] a) {
int[] b = new int[a.length];
for (int i = 0; i < a.length; i++) {
b[b.length - i - 1] = a[i];
}
return b;
}
private static long[] reverse(long[] a) {
long[] b = new long[a.length];
for (int i = 0; i < a.length; i++) {
b[b.length - i - 1] = a[i];
}
return b;
}
private static double[] reverse(double[] a) {
double[] b = new double[a.length];
for (int i = 0; i < a.length; i++) {
b[b.length - i - 1] = a[i];
}
return b;
}
private void executeAndCatch(Runnable r) {
executeAndCatch(IllegalArgumentException.class, r);
}
private void executeAndNoCatch(Runnable r) {
executeAndCatch(null, r);
}
private void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
Exception caught = null;
try {
r.run();
}
catch (Exception e) {
caught = e;
}
if (expected != null) {
assertNotNull(caught,
String.format("No Exception was thrown, expected an Exception of %s to be thrown",
expected.getName()));
assertTrue(expected.isInstance(caught),
String.format("Exception thrown %s not an instance of %s",
caught.getClass().getName(), expected.getName()));
}
else {
if (caught != null) {
assertNull(caught,
String.format("Unexpected exception of %s was thrown",
caught.getClass().getName()));
}
}
}
// 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);
// }
// }
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册