8072727: add variation of Stream.iterate() that's finite
Reviewed-by: psandoz, briangoetz
--- a/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java Wed Mar 02 13:21:20 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java Thu Mar 03 10:06:16 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -949,24 +949,100 @@
*/
public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) {
Objects.requireNonNull(f);
- final PrimitiveIterator.OfDouble iterator = new PrimitiveIterator.OfDouble() {
- double t = seed;
+ Spliterator.OfDouble spliterator = new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ double prev;
+ boolean started;
@Override
- public boolean hasNext() {
+ public boolean tryAdvance(DoubleConsumer action) {
+ Objects.requireNonNull(action);
+ double t;
+ if (started)
+ t = f.applyAsDouble(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ action.accept(prev = t);
+ return true;
+ }
+ };
+ return StreamSupport.doubleStream(spliterator, false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code DoubleStream} produced by iterative
+ * application of a function to an initial element, conditioned on
+ * satisfying the supplied predicate. The stream terminates as soon as
+ * the predicate returns false.
+ *
+ * <p>
+ * {@code DoubleStream.iterate} should produce the same sequence of
+ * elements as produced by the corresponding for-loop:
+ * <pre>{@code
+ * for (double index=seed; predicate.test(index); index = f.apply(index)) {
+ * ...
+ * }
+ * }</pre>
+ *
+ * <p>
+ * The resulting sequence may be empty if the predicate does not hold on
+ * the seed value. Otherwise the first element will be the supplied seed
+ * value, the next element (if present) will be the result of applying the
+ * function f to the seed value, and so on iteratively until the predicate
+ * indicates that the stream should terminate.
+ *
+ * @param seed the initial element
+ * @param predicate a predicate to apply to elements to determine when the
+ * stream must terminate.
+ * @param f a function to be applied to the previous element to produce
+ * a new element
+ * @return a new sequential {@code DoubleStream}
+ * @since 9
+ */
+ public static DoubleStream iterate(double seed, DoublePredicate predicate, DoubleUnaryOperator f) {
+ Objects.requireNonNull(f);
+ Objects.requireNonNull(predicate);
+ Spliterator.OfDouble spliterator = new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ double prev;
+ boolean started, finished;
+
+ @Override
+ public boolean tryAdvance(DoubleConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return false;
+ double t;
+ if (started)
+ t = f.applyAsDouble(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ if (!predicate.test(t)) {
+ finished = true;
+ return false;
+ }
+ action.accept(prev = t);
return true;
}
@Override
- public double nextDouble() {
- double v = t;
- t = f.applyAsDouble(t);
- return v;
+ public void forEachRemaining(DoubleConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return;
+ finished = true;
+ double t = started ? f.applyAsDouble(prev) : seed;
+ while (predicate.test(t)) {
+ action.accept(t);
+ t = f.applyAsDouble(t);
+ }
}
};
- return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(
- iterator,
- Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
+ return StreamSupport.doubleStream(spliterator, false);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/stream/IntStream.java Wed Mar 02 13:21:20 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/util/stream/IntStream.java Thu Mar 03 10:06:16 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -885,28 +885,104 @@
* @param seed the initial element
* @param f a function to be applied to the previous element to produce
* a new element
- * @return A new sequential {@code IntStream}
+ * @return a new sequential {@code IntStream}
*/
public static IntStream iterate(final int seed, final IntUnaryOperator f) {
Objects.requireNonNull(f);
- final PrimitiveIterator.OfInt iterator = new PrimitiveIterator.OfInt() {
- int t = seed;
+ Spliterator.OfInt spliterator = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ int prev;
+ boolean started;
@Override
- public boolean hasNext() {
+ public boolean tryAdvance(IntConsumer action) {
+ Objects.requireNonNull(action);
+ int t;
+ if (started)
+ t = f.applyAsInt(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ action.accept(prev = t);
+ return true;
+ }
+ };
+ return StreamSupport.intStream(spliterator, false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code IntStream} produced by iterative
+ * application of a function to an initial element, conditioned on
+ * satisfying the supplied predicate. The stream terminates as soon as
+ * the predicate returns false.
+ *
+ * <p>
+ * {@code IntStream.iterate} should produce the same sequence of elements
+ * as produced by the corresponding for-loop:
+ * <pre>{@code
+ * for (int index=seed; predicate.test(index); index = f.apply(index)) {
+ * ...
+ * }
+ * }</pre>
+ *
+ * <p>
+ * The resulting sequence may be empty if the predicate does not hold on
+ * the seed value. Otherwise the first element will be the supplied seed
+ * value, the next element (if present) will be the result of applying the
+ * function f to the seed value, and so on iteratively until the predicate
+ * indicates that the stream should terminate.
+ *
+ * @param seed the initial element
+ * @param predicate a predicate to apply to elements to determine when the
+ * stream must terminate.
+ * @param f a function to be applied to the previous element to produce
+ * a new element
+ * @return a new sequential {@code IntStream}
+ * @since 9
+ */
+ public static IntStream iterate(int seed, IntPredicate predicate, IntUnaryOperator f) {
+ Objects.requireNonNull(f);
+ Objects.requireNonNull(predicate);
+ Spliterator.OfInt spliterator = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ int prev;
+ boolean started, finished;
+
+ @Override
+ public boolean tryAdvance(IntConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return false;
+ int t;
+ if (started)
+ t = f.applyAsInt(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ if (!predicate.test(t)) {
+ finished = true;
+ return false;
+ }
+ action.accept(prev = t);
return true;
}
@Override
- public int nextInt() {
- int v = t;
- t = f.applyAsInt(t);
- return v;
+ public void forEachRemaining(IntConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return;
+ finished = true;
+ int t = started ? f.applyAsInt(prev) : seed;
+ while (predicate.test(t)) {
+ action.accept(t);
+ t = f.applyAsInt(t);
+ }
}
};
- return StreamSupport.intStream(Spliterators.spliteratorUnknownSize(
- iterator,
- Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
+ return StreamSupport.intStream(spliterator, false);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/stream/LongStream.java Wed Mar 02 13:21:20 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/util/stream/LongStream.java Thu Mar 03 10:06:16 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -879,24 +879,100 @@
*/
public static LongStream iterate(final long seed, final LongUnaryOperator f) {
Objects.requireNonNull(f);
- final PrimitiveIterator.OfLong iterator = new PrimitiveIterator.OfLong() {
- long t = seed;
+ Spliterator.OfLong spliterator = new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ long prev;
+ boolean started;
@Override
- public boolean hasNext() {
+ public boolean tryAdvance(LongConsumer action) {
+ Objects.requireNonNull(action);
+ long t;
+ if (started)
+ t = f.applyAsLong(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ action.accept(prev = t);
+ return true;
+ }
+ };
+ return StreamSupport.longStream(spliterator, false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code LongStream} produced by iterative
+ * application of a function to an initial element, conditioned on
+ * satisfying the supplied predicate. The stream terminates as soon as
+ * the predicate returns false.
+ *
+ * <p>
+ * {@code LongStream.iterate} should produce the same sequence of elements
+ * as produced by the corresponding for-loop:
+ * <pre>{@code
+ * for (long index=seed; predicate.test(index); index = f.apply(index)) {
+ * ...
+ * }
+ * }</pre>
+ *
+ * <p>
+ * The resulting sequence may be empty if the predicate does not hold on
+ * the seed value. Otherwise the first element will be the supplied seed
+ * value, the next element (if present) will be the result of applying the
+ * function f to the seed value, and so on iteratively until the predicate
+ * indicates that the stream should terminate.
+ *
+ * @param seed the initial element
+ * @param predicate a predicate to apply to elements to determine when the
+ * stream must terminate.
+ * @param f a function to be applied to the previous element to produce
+ * a new element
+ * @return a new sequential {@code LongStream}
+ * @since 9
+ */
+ public static LongStream iterate(long seed, LongPredicate predicate, LongUnaryOperator f) {
+ Objects.requireNonNull(f);
+ Objects.requireNonNull(predicate);
+ Spliterator.OfLong spliterator = new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ long prev;
+ boolean started, finished;
+
+ @Override
+ public boolean tryAdvance(LongConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return false;
+ long t;
+ if (started)
+ t = f.applyAsLong(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ if (!predicate.test(t)) {
+ finished = true;
+ return false;
+ }
+ action.accept(prev = t);
return true;
}
@Override
- public long nextLong() {
- long v = t;
- t = f.applyAsLong(t);
- return v;
+ public void forEachRemaining(LongConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return;
+ finished = true;
+ long t = started ? f.applyAsLong(prev) : seed;
+ while (predicate.test(t)) {
+ action.accept(t);
+ t = f.applyAsLong(t);
+ }
}
};
- return StreamSupport.longStream(Spliterators.spliteratorUnknownSize(
- iterator,
- Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
+ return StreamSupport.longStream(spliterator, false);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/stream/Stream.java Wed Mar 02 13:21:20 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/util/stream/Stream.java Thu Mar 03 10:06:16 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
-import java.util.Iterator;
import java.util.Objects;
import java.util.Optional;
import java.util.Spliterator;
@@ -1185,23 +1184,103 @@
*/
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
Objects.requireNonNull(f);
- final Iterator<T> iterator = new Iterator<T>() {
- @SuppressWarnings("unchecked")
- T t = (T) Streams.NONE;
+ Spliterator<T> spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE) {
+ T prev;
+ boolean started;
@Override
- public boolean hasNext() {
+ public boolean tryAdvance(Consumer<? super T> action) {
+ Objects.requireNonNull(action);
+ T t;
+ if (started)
+ t = f.apply(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ action.accept(prev = t);
+ return true;
+ }
+ };
+ return StreamSupport.stream(spliterator, false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code Stream} produced by iterative
+ * application of a function to an initial element, conditioned on
+ * satisfying the supplied predicate. The stream terminates as soon as
+ * the predicate returns false.
+ *
+ * <p>
+ * {@code Stream.iterate} should produce the same sequence of elements as
+ * produced by the corresponding for-loop:
+ * <pre>{@code
+ * for (T index=seed; predicate.test(index); index = f.apply(index)) {
+ * ...
+ * }
+ * }</pre>
+ *
+ * <p>
+ * The resulting sequence may be empty if the predicate does not hold on
+ * the seed value. Otherwise the first element will be the supplied seed
+ * value, the next element (if present) will be the result of applying the
+ * function f to the seed value, and so on iteratively until the predicate
+ * indicates that the stream should terminate.
+ *
+ * @param <T> the type of stream elements
+ * @param seed the initial element
+ * @param predicate a predicate to apply to elements to determine when the
+ * stream must terminate.
+ * @param f a function to be applied to the previous element to produce
+ * a new element
+ * @return a new sequential {@code Stream}
+ * @since 9
+ */
+ public static<T> Stream<T> iterate(T seed, Predicate<? super T> predicate, UnaryOperator<T> f) {
+ Objects.requireNonNull(f);
+ Objects.requireNonNull(predicate);
+ Spliterator<T> spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE) {
+ T prev;
+ boolean started, finished;
+
+ @Override
+ public boolean tryAdvance(Consumer<? super T> action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return false;
+ T t;
+ if (started)
+ t = f.apply(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ if (!predicate.test(t)) {
+ prev = null;
+ finished = true;
+ return false;
+ }
+ action.accept(prev = t);
return true;
}
@Override
- public T next() {
- return t = (t == Streams.NONE) ? seed : f.apply(t);
+ public void forEachRemaining(Consumer<? super T> action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return;
+ finished = true;
+ T t = started ? f.apply(prev) : seed;
+ prev = null;
+ while (predicate.test(t)) {
+ action.accept(t);
+ t = f.apply(t);
+ }
}
};
- return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
- iterator,
- Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
+ return StreamSupport.stream(spliterator, false);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/stream/Streams.java Wed Mar 02 13:21:20 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/util/stream/Streams.java Thu Mar 03 10:06:16 2016 +0100
@@ -49,14 +49,6 @@
}
/**
- * An object instance representing no value, that cannot be an actual
- * data element of a stream. Used when processing streams that can contain
- * {@code null} elements to distinguish between a {@code null} value and no
- * value.
- */
- static final Object NONE = new Object();
-
- /**
* An {@code int} range spliterator.
*/
static final class RangeIntSpliterator implements Spliterator.OfInt {
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java Wed Mar 02 13:21:20 2016 -0800
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java Thu Mar 03 10:06:16 2016 +0100
@@ -126,6 +126,9 @@
() -> Spliterators.spliterator(isl.iterator(), doubles.length, 0)));
spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator()):" + name,
() -> Spliterators.spliteratorUnknownSize(isl.iterator(), 0)));
+ spliterators.add(splitDescr("DoubleStream.iterate(0,x->x<l;x->x+1):" + name,
+ () -> DoubleStream.iterate(0.0, x -> x < doubles.length, x -> x + 1.0)
+ .spliterator()));
// Need more!
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java Wed Mar 02 13:21:20 2016 -0800
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java Thu Mar 03 10:06:16 2016 +0100
@@ -136,6 +136,8 @@
() -> IntStream.range(0, ints.length).spliterator()));
spliterators.add(splitDescr("IntStream.intRangeClosed(0,l):" + name,
() -> IntStream.rangeClosed(0, ints.length).spliterator()));
+ spliterators.add(splitDescr("IntStream.iterate(0,x->x<l,x->x+1): " + name,
+ () -> IntStream.iterate(0, x -> x < ints.length, x -> x + 1).spliterator()));
// Need more!
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java Wed Mar 02 13:21:20 2016 -0800
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java Thu Mar 03 10:06:16 2016 +0100
@@ -136,6 +136,9 @@
() -> LongStream.range(0, longs.length).spliterator()));
spliterators.add(splitDescr("LongStream.longRangeClosed(0,l):" + name,
() -> LongStream.rangeClosed(0, longs.length).spliterator()));
+ spliterators.add(splitDescr("LongStream.iterate(0,x->x<l;x->x+1):" + name,
+ () -> LongStream.iterate(0L, x -> x < longs.length, x -> x + 1L)
+ .spliterator()));
// Need more!
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java Wed Mar 02 13:21:20 2016 -0800
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java Thu Mar 03 10:06:16 2016 +0100
@@ -171,6 +171,8 @@
() -> Spliterators.spliterator(Arrays.asList(ints).iterator(), ints.length, 0)));
spliterators.add(splitDescr("Iterators.s(Arrays.s(array).iterator()):" + name,
() -> Spliterators.spliteratorUnknownSize(Arrays.asList(ints).iterator(), 0)));
+ spliterators.add(splitDescr("Stream.iterate(0,x->x<l,x->x+1): " + name,
+ () -> Stream.iterate(0, x -> x < ints.length, x -> x + 1).spliterator()));
// @@@ Add map and collection spliterators when spliterator() is exposed on Collection or Iterable
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java Thu Mar 03 10:06:16 2016 +0100
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8072727
+ */
+
+package org.openjdk.tests.java.util.stream;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.OpTestCase;
+import java.util.stream.Stream;
+import java.util.stream.TestData;
+import java.util.stream.TestData.Factory;
+
+import static java.util.stream.ThowableHelper.checkNPE;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@Test
+public class IterateTest extends OpTestCase {
+
+ @DataProvider(name = "IterateStreamsData")
+ public static Object[][] makeIterateStreamsTestData() {
+ Object[][] data = {
+ {List.of(),
+ Factory.ofSupplier("ref.empty", () -> Stream.iterate(1, x -> x < 0, x -> x * 2))},
+ {List.of(1),
+ Factory.ofSupplier("ref.one", () -> Stream.iterate(1, x -> x < 2, x -> x * 2))},
+ {List.of(1, 2, 4, 8, 16, 32, 64, 128, 256, 512),
+ Factory.ofSupplier("ref.ten", () -> Stream.iterate(1, x -> x < 1000, x -> x * 2))},
+ {List.of(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
+ Factory.ofSupplier("ref.nullCheck", () -> Stream.iterate(10, Objects::nonNull, x -> x > 0 ? x - 1 : null))},
+ {List.of(),
+ Factory.ofIntSupplier("int.empty", () -> IntStream.iterate(1, x -> x < 0, x -> x + 1))},
+ {List.of(1),
+ Factory.ofIntSupplier("int.one", () -> IntStream.iterate(1, x -> x < 2, x -> x + 1))},
+ {List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
+ Factory.ofIntSupplier("int.ten", () -> IntStream.iterate(1, x -> x <= 10, x -> x + 1))},
+ {List.of(5, 4, 3, 2, 1),
+ Factory.ofIntSupplier("int.divZero", () -> IntStream.iterate(5, x -> x != 0, x -> x - 1/x/2 - 1))},
+ {List.of(),
+ Factory.ofLongSupplier("long.empty", () -> LongStream.iterate(1L, x -> x < 0, x -> x + 1))},
+ {List.of(1L),
+ Factory.ofLongSupplier("long.one", () -> LongStream.iterate(1L, x -> x < 2, x -> x + 1))},
+ {List.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L),
+ Factory.ofLongSupplier("long.ten", () -> LongStream.iterate(1L, x -> x <= 10, x -> x + 1))},
+ {List.of(),
+ Factory.ofDoubleSupplier("double.empty", () -> DoubleStream.iterate(1.0, x -> x < 0, x -> x + 1))},
+ {List.of(1.0),
+ Factory.ofDoubleSupplier("double.one", () -> DoubleStream.iterate(1.0, x -> x < 2, x -> x + 1))},
+ {List.of(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0),
+ Factory.ofDoubleSupplier("double.ten", () -> DoubleStream.iterate(1.0, x -> x <= 10, x -> x + 1))}
+ };
+ return data;
+ }
+
+ @Test(dataProvider = "IterateStreamsData")
+ public <T> void testIterate(List<T> expected, TestData<T, ?> data) {
+ withData(data).stream(s -> s).expectedResult(expected).exercise();
+ }
+
+ @Test
+ public void testNPE() {
+ checkNPE(() -> Stream.iterate("", null, x -> x + "a"));
+ checkNPE(() -> Stream.iterate("", String::isEmpty, null));
+ checkNPE(() -> IntStream.iterate(0, null, x -> x + 1));
+ checkNPE(() -> IntStream.iterate(0, x -> x < 10, null));
+ checkNPE(() -> LongStream.iterate(0, null, x -> x + 1));
+ checkNPE(() -> LongStream.iterate(0, x -> x < 10, null));
+ checkNPE(() -> DoubleStream.iterate(0, null, x -> x + 1));
+ checkNPE(() -> DoubleStream.iterate(0, x -> x < 10, null));
+ }
+}