Merge
This commit is contained in:
commit
6788137f6f
@ -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;
|
||||
}
|
||||
return hasNext;
|
||||
else if (last > 0) {
|
||||
last = 0;
|
||||
consumer.accept(i);
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
return hasNext;
|
||||
else if (last > 0) {
|
||||
last = 0;
|
||||
consumer.accept(i);
|
||||
return true;
|
||||
}
|
||||
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, int step) {
|
||||
return TestData.Factory.ofIntSupplier("int range", () -> IntStream.range(start, end, step));
|
||||
TestData.OfInt intRangeData(int start, int end) {
|
||||
return TestData.Factory.ofIntSupplier("int range", () -> IntStream.range(start, end));
|
||||
}
|
||||
|
||||
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, long step) {
|
||||
return TestData.Factory.ofLongSupplier("long range", () -> LongStream.range(start, end, step));
|
||||
TestData.OfLong longRangeData(long start, long end) {
|
||||
return TestData.Factory.ofLongSupplier("long range", () -> LongStream.range(start, end));
|
||||
}
|
||||
|
||||
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);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user