8012650: Arrays streams methods
8011918: java.util.stream.Streams
Reviewed-by: alanb, mduigou, darcy, henryjen
Contributed-by: brian.goetz@oracle.com, paul.sandoz@oracle.com
--- a/jdk/src/share/classes/java/util/Arrays.java Mon Apr 29 18:12:28 2013 +0100
+++ b/jdk/src/share/classes/java/util/Arrays.java Sat Apr 20 18:53:26 2013 -0400
@@ -25,7 +25,21 @@
package java.util;
-import java.lang.reflect.*;
+import java.lang.reflect.Array;
+import java.util.concurrent.ForkJoinPool;
+import java.util.function.BinaryOperator;
+import java.util.function.DoubleBinaryOperator;
+import java.util.function.IntBinaryOperator;
+import java.util.function.IntFunction;
+import java.util.function.IntToDoubleFunction;
+import java.util.function.IntToLongFunction;
+import java.util.function.IntUnaryOperator;
+import java.util.function.LongBinaryOperator;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
import static java.util.ArraysParallelSortHelpers.*;
/**
@@ -4306,17 +4320,171 @@
dejaVu.remove(a);
}
+
/**
- * Creates a {@link Spliterator} covering all of the specified array.
+ * Set all elements of the specified array, using the provided
+ * generator function to compute each element.
+ *
+ * <p>If the generator function throws an exception, it is relayed to
+ * the caller and the array is left in an indeterminate state.
+ *
+ * @param <T> type of elements of the array
+ * @param array array to be initialized
+ * @param generator a function accepting an index and producing the desired
+ * value for that position
+ * @throws NullPointerException if the generator is null
+ * @since 1.8
+ */
+ public static <T> void setAll(T[] array, IntFunction<? extends T> generator) {
+ Objects.requireNonNull(generator);
+ for (int i = 0; i < array.length; i++)
+ array[i] = generator.apply(i);
+ }
+
+ /**
+ * Set all elements of the specified array, in parallel, using the
+ * provided generator function to compute each element.
+ *
+ * <p>If the generator function throws an exception, an unchecked exception
+ * is thrown from {@code parallelSetAll} and the array is left in an
+ * indeterminate state.
+ *
+ * @param <T> type of elements of the array
+ * @param array array to be initialized
+ * @param generator a function accepting an index and producing the desired
+ * value for that position
+ * @throws NullPointerException if the generator is null
+ * @since 1.8
+ */
+ public static <T> void parallelSetAll(T[] array, IntFunction<? extends T> generator) {
+ Objects.requireNonNull(generator);
+ IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.apply(i); });
+ }
+
+ /**
+ * Set all elements of the specified array, using the provided
+ * generator function to compute each element.
+ *
+ * <p>If the generator function throws an exception, it is relayed to
+ * the caller and the array is left in an indeterminate state.
+ *
+ * @param array array to be initialized
+ * @param generator a function accepting an index and producing the desired
+ * value for that position
+ * @throws NullPointerException if the generator is null
+ * @since 1.8
+ */
+ public static void setAll(int[] array, IntUnaryOperator generator) {
+ Objects.requireNonNull(generator);
+ for (int i = 0; i < array.length; i++)
+ array[i] = generator.applyAsInt(i);
+ }
+
+ /**
+ * Set all elements of the specified array, in parallel, using the
+ * provided generator function to compute each element.
+ *
+ * <p>If the generator function throws an exception, an unchecked exception
+ * is thrown from {@code parallelSetAll} and the array is left in an
+ * indeterminate state.
+ *
+ * @param array array to be initialized
+ * @param generator a function accepting an index and producing the desired
+ * value for that position
+ * @throws NullPointerException if the generator is null
+ * @since 1.8
+ */
+ public static void parallelSetAll(int[] array, IntUnaryOperator generator) {
+ Objects.requireNonNull(generator);
+ IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsInt(i); });
+ }
+
+ /**
+ * Set all elements of the specified array, using the provided
+ * generator function to compute each element.
+ *
+ * <p>If the generator function throws an exception, it is relayed to
+ * the caller and the array is left in an indeterminate state.
+ *
+ * @param array array to be initialized
+ * @param generator a function accepting an index and producing the desired
+ * value for that position
+ * @throws NullPointerException if the generator is null
+ * @since 1.8
+ */
+ public static void setAll(long[] array, IntToLongFunction generator) {
+ Objects.requireNonNull(generator);
+ for (int i = 0; i < array.length; i++)
+ array[i] = generator.applyAsLong(i);
+ }
+
+ /**
+ * Set all elements of the specified array, in parallel, using the
+ * provided generator function to compute each element.
+ *
+ * <p>If the generator function throws an exception, an unchecked exception
+ * is thrown from {@code parallelSetAll} and the array is left in an
+ * indeterminate state.
+ *
+ * @param array array to be initialized
+ * @param generator a function accepting an index and producing the desired
+ * value for that position
+ * @throws NullPointerException if the generator is null
+ * @since 1.8
+ */
+ public static void parallelSetAll(long[] array, IntToLongFunction generator) {
+ Objects.requireNonNull(generator);
+ IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsLong(i); });
+ }
+
+ /**
+ * Set all elements of the specified array, using the provided
+ * generator function to compute each element.
+ *
+ * <p>If the generator function throws an exception, it is relayed to
+ * the caller and the array is left in an indeterminate state.
+ *
+ * @param array array to be initialized
+ * @param generator a function accepting an index and producing the desired
+ * value for that position
+ * @throws NullPointerException if the generator is null
+ * @since 1.8
+ */
+ public static void setAll(double[] array, IntToDoubleFunction generator) {
+ Objects.requireNonNull(generator);
+ for (int i = 0; i < array.length; i++)
+ array[i] = generator.applyAsDouble(i);
+ }
+
+ /**
+ * Set all elements of the specified array, in parallel, using the
+ * provided generator function to compute each element.
+ *
+ * <p>If the generator function throws an exception, an unchecked exception
+ * is thrown from {@code parallelSetAll} and the array is left in an
+ * indeterminate state.
+ *
+ * @param array array to be initialized
+ * @param generator a function accepting an index and producing the desired
+ * value for that position
+ * @throws NullPointerException if the generator is null
+ * @since 1.8
+ */
+ public static void parallelSetAll(double[] array, IntToDoubleFunction generator) {
+ Objects.requireNonNull(generator);
+ IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsDouble(i); });
+ }
+
+ /**
+ * Returns a {@link Spliterator} covering all of the specified array.
*
* <p>The spliterator reports {@link Spliterator#SIZED},
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
* {@link Spliterator#IMMUTABLE}.
*
- * @param <T> Type of elements
- * @param array The array, assumed to be unmodified during use
- * @return A spliterator from the array
- * @throws NullPointerException if the specified array is {@code null}
+ * @param <T> type of elements
+ * @param array the array, assumed to be unmodified during use
+ * @return a spliterator for the array elements
* @since 1.8
*/
public static <T> Spliterator<T> spliterator(T[] array) {
@@ -4325,39 +4493,38 @@
}
/**
- * Creates a {@link Spliterator} covering the specified range of the
+ * Returns a {@link Spliterator} covering the specified range of the
* specified array.
*
* <p>The spliterator reports {@link Spliterator#SIZED},
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
* {@link Spliterator#IMMUTABLE}.
*
- * @param <T> Type of elements
- * @param array The array, assumed to be unmodified during use
- * @param fromIndex The least index (inclusive) to cover
- * @param toIndex One past the greatest index to cover
- * @return A spliterator from the array
- * @throws NullPointerException if the specified array is {@code null}
- * @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
- * {@code toIndex} is less than {@code fromIndex}, or
- * {@code toIndex} is greater than the array size
+ * @param <T> type of elements
+ * @param array the array, assumed to be unmodified during use
+ * @param startInclusive the first index to cover, inclusive
+ * @param endExclusive index immediately past the last index to cover
+ * @return a spliterator for the array elements
+ * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
+ * negative, {@code endExclusive} is less than
+ * {@code startInclusive}, or {@code endExclusive} is greater than
+ * the array size
* @since 1.8
*/
- public static <T> Spliterator<T> spliterator(T[] array, int fromIndex, int toIndex) {
- return Spliterators.spliterator(array, fromIndex, toIndex,
+ public static <T> Spliterator<T> spliterator(T[] array, int startInclusive, int endExclusive) {
+ return Spliterators.spliterator(array, startInclusive, endExclusive,
Spliterator.ORDERED | Spliterator.IMMUTABLE);
}
/**
- * Creates a {@link Spliterator.OfInt} covering all of the specified array.
+ * Returns a {@link Spliterator.OfInt} covering all of the specified array.
*
* <p>The spliterator reports {@link Spliterator#SIZED},
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
* {@link Spliterator#IMMUTABLE}.
*
- * @param array The array, assumed to be unmodified during use
- * @return A spliterator from the array
- * @throws NullPointerException if the specified array is {@code null}
+ * @param array the array, assumed to be unmodified during use
+ * @return a spliterator for the array elements
* @since 1.8
*/
public static Spliterator.OfInt spliterator(int[] array) {
@@ -4366,38 +4533,37 @@
}
/**
- * Creates a {@link Spliterator.OfInt} covering the specified range of the
+ * Returns a {@link Spliterator.OfInt} covering the specified range of the
* specified array.
*
* <p>The spliterator reports {@link Spliterator#SIZED},
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
* {@link Spliterator#IMMUTABLE}.
*
- * @param array The array, assumed to be unmodified during use
- * @param fromIndex The least index (inclusive) to cover
- * @param toIndex One past the greatest index to cover
- * @return A spliterator from the array
- * @throws NullPointerException if the specified array is {@code null}
- * @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
- * {@code toIndex} is less than {@code fromIndex}, or
- * {@code toIndex} is greater than the array size
+ * @param array the array, assumed to be unmodified during use
+ * @param startInclusive the first index to cover, inclusive
+ * @param endExclusive index immediately past the last index to cover
+ * @return a spliterator for the array elements
+ * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
+ * negative, {@code endExclusive} is less than
+ * {@code startInclusive}, or {@code endExclusive} is greater than
+ * the array size
* @since 1.8
*/
- public static Spliterator.OfInt spliterator(int[] array, int fromIndex, int toIndex) {
- return Spliterators.spliterator(array, fromIndex, toIndex,
+ public static Spliterator.OfInt spliterator(int[] array, int startInclusive, int endExclusive) {
+ return Spliterators.spliterator(array, startInclusive, endExclusive,
Spliterator.ORDERED | Spliterator.IMMUTABLE);
}
/**
- * Creates a {@link Spliterator.OfLong} covering all of the specified array.
+ * Returns a {@link Spliterator.OfLong} covering all of the specified array.
*
* <p>The spliterator reports {@link Spliterator#SIZED},
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
* {@link Spliterator#IMMUTABLE}.
*
- * @param array The array, assumed to be unmodified during use
- * @return A spliterator from the array
- * @throws NullPointerException if the specified array is {@code null}
+ * @param array the array, assumed to be unmodified during use
+ * @return the spliterator for the array elements
* @since 1.8
*/
public static Spliterator.OfLong spliterator(long[] array) {
@@ -4406,39 +4572,38 @@
}
/**
- * Creates a {@link Spliterator.OfLong} covering the specified range of the
+ * Returns a {@link Spliterator.OfLong} covering the specified range of the
* specified array.
*
* <p>The spliterator reports {@link Spliterator#SIZED},
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
* {@link Spliterator#IMMUTABLE}.
*
- * @param array The array, assumed to be unmodified during use
- * @param fromIndex The least index (inclusive) to cover
- * @param toIndex One past the greatest index to cover
- * @return A spliterator from the array
- * @throws NullPointerException if the specified array is {@code null}
- * @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
- * {@code toIndex} is less than {@code fromIndex}, or
- * {@code toIndex} is greater than the array size
+ * @param array the array, assumed to be unmodified during use
+ * @param startInclusive the first index to cover, inclusive
+ * @param endExclusive index immediately past the last index to cover
+ * @return a spliterator for the array elements
+ * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
+ * negative, {@code endExclusive} is less than
+ * {@code startInclusive}, or {@code endExclusive} is greater than
+ * the array size
* @since 1.8
*/
- public static Spliterator.OfLong spliterator(long[] array, int fromIndex, int toIndex) {
- return Spliterators.spliterator(array, fromIndex, toIndex,
+ public static Spliterator.OfLong spliterator(long[] array, int startInclusive, int endExclusive) {
+ return Spliterators.spliterator(array, startInclusive, endExclusive,
Spliterator.ORDERED | Spliterator.IMMUTABLE);
}
/**
- * Creates a {@link Spliterator.OfDouble} covering all of the specified
+ * Returns a {@link Spliterator.OfDouble} covering all of the specified
* array.
*
* <p>The spliterator reports {@link Spliterator#SIZED},
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
* {@link Spliterator#IMMUTABLE}.
*
- * @param array The array, assumed to be unmodified during use
- * @return A spliterator from the array
- * @throws NullPointerException if the specified array is {@code null}
+ * @param array the array, assumed to be unmodified during use
+ * @return a spliterator for the array elements
* @since 1.8
*/
public static Spliterator.OfDouble spliterator(double[] array) {
@@ -4447,25 +4612,147 @@
}
/**
- * Creates a {@link Spliterator.OfDouble} covering the specified range of
+ * Returns a {@link Spliterator.OfDouble} covering the specified range of
* the specified array.
*
* <p>The spliterator reports {@link Spliterator#SIZED},
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
* {@link Spliterator#IMMUTABLE}.
*
+ * @param array the array, assumed to be unmodified during use
+ * @param startInclusive the first index to cover, inclusive
+ * @param endExclusive index immediately past the last index to cover
+ * @return a spliterator for the array elements
+ * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
+ * negative, {@code endExclusive} is less than
+ * {@code startInclusive}, or {@code endExclusive} is greater than
+ * the array size
+ * @since 1.8
+ */
+ public static Spliterator.OfDouble spliterator(double[] array, int startInclusive, int endExclusive) {
+ return Spliterators.spliterator(array, startInclusive, endExclusive,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE);
+ }
+
+ /**
+ * Returns a sequential {@link Stream} with the specified array as its
+ * source.
+ *
+ * @param <T> The type of the array elements
* @param array The array, assumed to be unmodified during use
- * @param fromIndex The least index (inclusive) to cover
- * @param toIndex One past the greatest index to cover
- * @return A spliterator from the array
- * @throws NullPointerException if the specified array is {@code null}
- * @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
- * {@code toIndex} is less than {@code fromIndex}, or
- * {@code toIndex} is greater than the array size
+ * @return a {@code Stream} for the array
+ * @since 1.8
+ */
+ public static <T> Stream<T> stream(T[] array) {
+ return stream(array, 0, array.length);
+ }
+
+ /**
+ * Returns a sequential {@link Stream} with the specified range of the
+ * specified array as its source.
+ *
+ * @param <T> the type of the array elements
+ * @param array the array, assumed to be unmodified during use
+ * @param startInclusive the first index to cover, inclusive
+ * @param endExclusive index immediately past the last index to cover
+ * @return a {@code Stream} for the array range
+ * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
+ * negative, {@code endExclusive} is less than
+ * {@code startInclusive}, or {@code endExclusive} is greater than
+ * the array size
+ * @since 1.8
+ */
+ public static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive) {
+ return StreamSupport.stream(spliterator(array, startInclusive, endExclusive));
+ }
+
+ /**
+ * Returns a sequential {@link IntStream} with the specified array as its
+ * source.
+ *
+ * @param array the array, assumed to be unmodified during use
+ * @return an {@code IntStream} for the array
* @since 1.8
*/
- public static Spliterator.OfDouble spliterator(double[] array, int fromIndex, int toIndex) {
- return Spliterators.spliterator(array, fromIndex, toIndex,
- Spliterator.ORDERED | Spliterator.IMMUTABLE);
+ public static IntStream stream(int[] array) {
+ return stream(array, 0, array.length);
+ }
+
+ /**
+ * Returns a sequential {@link IntStream} with the specified range of the
+ * specified array as its source.
+ *
+ * @param array the array, assumed to be unmodified during use
+ * @param startInclusive the first index to cover, inclusive
+ * @param endExclusive index immediately past the last index to cover
+ * @return an {@code IntStream} for the array range
+ * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
+ * negative, {@code endExclusive} is less than
+ * {@code startInclusive}, or {@code endExclusive} is greater than
+ * the array size
+ * @since 1.8
+ */
+ public static IntStream stream(int[] array, int startInclusive, int endExclusive) {
+ return StreamSupport.intStream(spliterator(array, startInclusive, endExclusive));
+ }
+
+ /**
+ * Returns a sequential {@link LongStream} with the specified array as its
+ * source.
+ *
+ * @param array the array, assumed to be unmodified during use
+ * @return a {@code LongStream} for the array
+ * @since 1.8
+ */
+ public static LongStream stream(long[] array) {
+ return stream(array, 0, array.length);
+ }
+
+ /**
+ * Returns a sequential {@link LongStream} with the specified range of the
+ * specified array as its source.
+ *
+ * @param array the array, assumed to be unmodified during use
+ * @param startInclusive the first index to cover, inclusive
+ * @param endExclusive index immediately past the last index to cover
+ * @return a {@code LongStream} for the array range
+ * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
+ * negative, {@code endExclusive} is less than
+ * {@code startInclusive}, or {@code endExclusive} is greater than
+ * the array size
+ * @since 1.8
+ */
+ public static LongStream stream(long[] array, int startInclusive, int endExclusive) {
+ return StreamSupport.longStream(spliterator(array, startInclusive, endExclusive));
+ }
+
+ /**
+ * Returns a sequential {@link DoubleStream} with the specified array as its
+ * source.
+ *
+ * @param array the array, assumed to be unmodified during use
+ * @return a {@code DoubleStream} for the array
+ * @since 1.8
+ */
+ public static DoubleStream stream(double[] array) {
+ return stream(array, 0, array.length);
+ }
+
+ /**
+ * Returns a sequential {@link DoubleStream} with the specified range of the
+ * specified array as its source.
+ *
+ * @param array the array, assumed to be unmodified during use
+ * @param startInclusive the first index to cover, inclusive
+ * @param endExclusive index immediately past the last index to cover
+ * @return a {@code DoubleStream} for the array range
+ * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
+ * negative, {@code endExclusive} is less than
+ * {@code startInclusive}, or {@code endExclusive} is greater than
+ * the array size
+ * @since 1.8
+ */
+ public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) {
+ return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive));
}
}
--- a/jdk/src/share/classes/java/util/stream/DoubleStream.java Mon Apr 29 18:12:28 2013 +0100
+++ b/jdk/src/share/classes/java/util/stream/DoubleStream.java Sat Apr 20 18:53:26 2013 -0400
@@ -24,15 +24,19 @@
*/
package java.util.stream;
+import java.util.Arrays;
import java.util.DoubleSummaryStatistics;
+import java.util.Objects;
import java.util.OptionalDouble;
import java.util.PrimitiveIterator;
import java.util.Spliterator;
+import java.util.Spliterators;
import java.util.function.BiConsumer;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleConsumer;
import java.util.function.DoubleFunction;
import java.util.function.DoublePredicate;
+import java.util.function.DoubleSupplier;
import java.util.function.DoubleToIntFunction;
import java.util.function.DoubleToLongFunction;
import java.util.function.DoubleUnaryOperator;
@@ -649,4 +653,175 @@
@Override
Spliterator.OfDouble spliterator();
+
+
+ // Static factories
+
+ /**
+ * Returns a builder for a {@code DoubleStream}.
+ *
+ * @return a stream builder
+ */
+ public static StreamBuilder.OfDouble builder() {
+ return new Streams.DoubleStreamBuilderImpl();
+ }
+
+ /**
+ * Returns an empty sequential {@code DoubleStream}.
+ *
+ * @return an empty sequential stream
+ */
+ public static DoubleStream empty() {
+ return StreamSupport.doubleStream(Spliterators.emptyDoubleSpliterator());
+ }
+
+ /**
+ * Returns a sequential {@code DoubleStream} containing a single element.
+ *
+ * @param t the single element
+ * @return a singleton sequential stream
+ */
+ public static DoubleStream of(double t) {
+ return StreamSupport.doubleStream(new Streams.DoubleStreamBuilderImpl(t));
+ }
+
+ /**
+ * Returns a sequential stream whose elements are the specified values.
+ *
+ * @param values the elements of the new stream
+ * @return the new stream
+ */
+ public static DoubleStream of(double... values) {
+ return Arrays.stream(values);
+ }
+
+ /**
+ * Returns an infinite sequential {@code DoubleStream} produced by iterative
+ * application of a function {@code f} to an initial element {@code seed},
+ * producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
+ * {@code f(f(seed))}, etc.
+ *
+ * <p>The first element (position {@code 0}) in the {@code DoubleStream}
+ * will be the provided {@code seed}. For {@code n > 0}, the element at
+ * position {@code n}, will be the result of applying the function {@code f}
+ * to the element at position {@code n - 1}.
+ *
+ * @param seed the initial element
+ * @param f a function to be applied to to the previous element to produce
+ * a new element
+ * @return a new sequential {@code DoubleStream}
+ */
+ public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) {
+ Objects.requireNonNull(f);
+ final PrimitiveIterator.OfDouble iterator = new PrimitiveIterator.OfDouble() {
+ double t = seed;
+
+ @Override
+ public boolean hasNext() {
+ return true;
+ }
+
+ @Override
+ public double nextDouble() {
+ double v = t;
+ t = f.applyAsDouble(t);
+ return v;
+ }
+ };
+ return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(
+ iterator,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL));
+ }
+
+ /**
+ * Returns a sequential {@code DoubleStream} where each element is
+ * generated by an {@code DoubleSupplier}. This is suitable for generating
+ * constant streams, streams of random elements, etc.
+ *
+ * @param s the {@code DoubleSupplier} for generated elements
+ * @return a new sequential {@code DoubleStream}
+ */
+ public static DoubleStream generate(DoubleSupplier s) {
+ Objects.requireNonNull(s);
+ return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(
+ new PrimitiveIterator.OfDouble() {
+ @Override
+ public boolean hasNext() { return true; }
+
+ @Override
+ public double nextDouble() { return s.getAsDouble(); }
+ },
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL));
+ }
+
+ /**
+ * Returns a sequential {@code DoubleStream} from {@code startInclusive} (inclusive)
+ * to {@code endExclusive} (exclusive) by an incremental step of 1.0.
+ *
+ * @implSpec
+ * The implementation behaves as if:
+ * <pre>{@code
+ * doubleRange(startInclusive, endExclusive, 1.0);
+ * }</pre>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endExclusive the exclusive upper bound
+ * @return a sequential {@code DoubleStream} for the range of {@code double}
+ * elements
+ */
+ public static DoubleStream range(double startInclusive, double endExclusive) {
+ return range(startInclusive, endExclusive, 1.0);
+ }
+
+ /**
+ * Returns a sequential {@code DoubleStream} 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.
+ *
+ * An equivalent sequence of increasing values can be produced
+ * sequentially using a {@code for} loop as follows:
+ * <pre>{@code
+ * long size = (long) Math.ceil((startInclusive - endExclusive) / step);
+ * long i = 0
+ * for (double v = startInclusive; i < size; i++, v = startInclusive + step * i) {
+ * ...
+ * }
+ * }</pre>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endExclusive the exclusive upper bound
+ * @param step the difference between consecutive values
+ * @return a sequential {@code DoubleStream} for tne range of {@code double}
+ * elements
+ * @throws IllegalArgumentException if {@code step} is less than or equal to
+ * 0. is {@code NaN}, or the count of elements in the range would be
+ * greater than {@code Long.MAX_VALUE}
+ */
+ public static DoubleStream range(double startInclusive, double endExclusive, double step) {
+ // @@@ Need to check for ranges that may not produce distinct values
+ // such as when the step is very small
+ // Also clarify the size of the range which may produce more or less
+ // than expected
+ if (step <= 0 || Double.isNaN(step)) {
+ throw new IllegalArgumentException(String.format("Illegal step: %f", step));
+ } else {
+ double range = endExclusive - startInclusive;
+ if (range <= 0) {
+ return empty();
+ }
+ double size = Math.ceil((endExclusive - startInclusive) / step);
+ if (Double.isNaN(size)) {
+ throw new IllegalArgumentException(
+ String.format("Illegal range: %f size is NaN", size));
+ } else if (size > Long.MAX_VALUE) {
+ throw new IllegalArgumentException(
+ String.format("Illegal range: size %f > Long.MAX_VALUE", size));
+ } else {
+ return StreamSupport.doubleStream(
+ new Streams.RangeDoubleSpliterator(
+ startInclusive, endExclusive, step, 0, (long) size));
+ }
+ }
+ }
}
--- a/jdk/src/share/classes/java/util/stream/IntStream.java Mon Apr 29 18:12:28 2013 +0100
+++ b/jdk/src/share/classes/java/util/stream/IntStream.java Sat Apr 20 18:53:26 2013 -0400
@@ -24,17 +24,21 @@
*/
package java.util.stream;
+import java.util.Arrays;
import java.util.IntSummaryStatistics;
+import java.util.Objects;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.PrimitiveIterator;
import java.util.Spliterator;
+import java.util.Spliterators;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.IntBinaryOperator;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.IntPredicate;
+import java.util.function.IntSupplier;
import java.util.function.IntToDoubleFunction;
import java.util.function.IntToLongFunction;
import java.util.function.IntUnaryOperator;
@@ -652,4 +656,153 @@
@Override
Spliterator.OfInt spliterator();
+
+ // Static factories
+
+ /**
+ * Returns a builder for an {@code IntStream}.
+ *
+ * @return a stream builder
+ */
+ public static StreamBuilder.OfInt builder() {
+ return new Streams.IntStreamBuilderImpl();
+ }
+
+ /**
+ * Returns an empty sequential {@code IntStream}.
+ *
+ * @return an empty sequential stream
+ */
+ public static IntStream empty() {
+ return StreamSupport.intStream(Spliterators.emptyIntSpliterator());
+ }
+
+ /**
+ * Returns a sequential {@code IntStream} containing a single element.
+ *
+ * @param t the single element
+ * @return a singleton sequential stream
+ */
+ public static IntStream of(int t) {
+ return StreamSupport.intStream(new Streams.IntStreamBuilderImpl(t));
+ }
+
+ /**
+ * Returns a sequential stream whose elements are the specified values.
+ *
+ * @param values the elements of the new stream
+ * @return the new stream
+ */
+ public static IntStream of(int... values) {
+ return Arrays.stream(values);
+ }
+
+ /**
+ * Returns an infinite sequential {@code IntStream} produced by iterative
+ * application of a function {@code f} to an initial element {@code seed},
+ * producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
+ * {@code f(f(seed))}, etc.
+ *
+ * <p>The first element (position {@code 0}) in the {@code IntStream} will be
+ * the provided {@code seed}. For {@code n > 0}, the element at position
+ * {@code n}, will be the result of applying the function {@code f} to the
+ * element at position {@code n - 1}.
+ *
+ * @param seed the initial element
+ * @param f a function to be applied to to the previous element to produce
+ * a new element
+ * @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;
+
+ @Override
+ public boolean hasNext() {
+ return true;
+ }
+
+ @Override
+ public int nextInt() {
+ int v = t;
+ t = f.applyAsInt(t);
+ return v;
+ }
+ };
+ return StreamSupport.intStream(Spliterators.spliteratorUnknownSize(
+ iterator,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL));
+ }
+
+ /**
+ * Returns a sequential {@code IntStream} where each element is
+ * generated by an {@code IntSupplier}. This is suitable for generating
+ * constant streams, streams of random elements, etc.
+ *
+ * @param s the {@code IntSupplier} for generated elements
+ * @return a new sequential {@code IntStream}
+ */
+ public static IntStream generate(IntSupplier s) {
+ Objects.requireNonNull(s);
+ return StreamSupport.intStream(Spliterators.spliteratorUnknownSize(
+ new PrimitiveIterator.OfInt() {
+ @Override
+ public boolean hasNext() { return true; }
+
+ @Override
+ public int nextInt() { return s.getAsInt(); }
+ },
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL));
+ }
+
+ /**
+ * Returns a sequential {@code IntStream} from {@code startInclusive}
+ * (inclusive) to {@code endExclusive} (exclusive) by an incremental step of
+ * 1.
+ *
+ * @implSpec
+ * The implementation behaves as if:
+ * <pre>{@code
+ * intRange(startInclusive, endExclusive, 1);
+ * }</pre>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endExclusive the exclusive upper bound
+ * @return a sequential {@code IntStream} for the range of {@code int}
+ * elements
+ */
+ public static IntStream range(int startInclusive, int endExclusive) {
+ return range(startInclusive, endExclusive, 1);
+ }
+
+ /**
+ * 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.
+ *
+ * <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) { ... }
+ * }</pre>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endExclusive the exclusive upper bound
+ * @param step the positive difference between consecutive values
+ * @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) {
+ return empty();
+ } else {
+ return StreamSupport.intStream(new Streams.RangeIntSpliterator(startInclusive, endExclusive, step));
+ }
+ }
}
--- a/jdk/src/share/classes/java/util/stream/LongStream.java Mon Apr 29 18:12:28 2013 +0100
+++ b/jdk/src/share/classes/java/util/stream/LongStream.java Sat Apr 20 18:53:26 2013 -0400
@@ -24,17 +24,21 @@
*/
package java.util.stream;
+import java.util.Arrays;
import java.util.LongSummaryStatistics;
+import java.util.Objects;
import java.util.OptionalDouble;
import java.util.OptionalLong;
import java.util.PrimitiveIterator;
import java.util.Spliterator;
+import java.util.Spliterators;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.LongBinaryOperator;
import java.util.function.LongConsumer;
import java.util.function.LongFunction;
import java.util.function.LongPredicate;
+import java.util.function.LongSupplier;
import java.util.function.LongToDoubleFunction;
import java.util.function.LongToIntFunction;
import java.util.function.LongUnaryOperator;
@@ -643,4 +647,153 @@
@Override
Spliterator.OfLong spliterator();
+
+ // Static factories
+
+ /**
+ * Returns a builder for a {@code LongStream}.
+ *
+ * @return a stream builder
+ */
+ public static StreamBuilder.OfLong builder() {
+ return new Streams.LongStreamBuilderImpl();
+ }
+
+ /**
+ * Returns an empty sequential {@code LongStream}.
+ *
+ * @return an empty sequential stream
+ */
+ public static LongStream empty() {
+ return StreamSupport.longStream(Spliterators.emptyLongSpliterator());
+ }
+
+ /**
+ * Returns a sequential {@code LongStream} containing a single element.
+ *
+ * @param t the single element
+ * @return a singleton sequential stream
+ */
+ public static LongStream of(long t) {
+ return StreamSupport.longStream(new Streams.LongStreamBuilderImpl(t));
+ }
+
+ /**
+ * Returns a sequential stream whose elements are the specified values.
+ *
+ * @param values the elements of the new stream
+ * @return the new stream
+ */
+ public static LongStream of(long... values) {
+ return Arrays.stream(values);
+ }
+
+ /**
+ * Returns an infinite sequential {@code LongStream} produced by iterative
+ * application of a function {@code f} to an initial element {@code seed},
+ * producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
+ * {@code f(f(seed))}, etc.
+ *
+ * <p>The first element (position {@code 0}) in the {@code LongStream} will
+ * be the provided {@code seed}. For {@code n > 0}, the element at position
+ * {@code n}, will be the result of applying the function {@code f} to the
+ * element at position {@code n - 1}.
+ *
+ * @param seed the initial element
+ * @param f a function to be applied to to the previous element to produce
+ * a new element
+ * @return a new sequential {@code LongStream}
+ */
+ public static LongStream iterate(final long seed, final LongUnaryOperator f) {
+ Objects.requireNonNull(f);
+ final PrimitiveIterator.OfLong iterator = new PrimitiveIterator.OfLong() {
+ long t = seed;
+
+ @Override
+ public boolean hasNext() {
+ return true;
+ }
+
+ @Override
+ public long nextLong() {
+ long v = t;
+ t = f.applyAsLong(t);
+ return v;
+ }
+ };
+ return StreamSupport.longStream(Spliterators.spliteratorUnknownSize(
+ iterator,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL));
+ }
+
+ /**
+ * Returns a sequential {@code LongStream} where each element is generated
+ * by a {@code LongSupplier}. This is suitable for generating constant
+ * streams, streams of random elements, etc.
+ *
+ * @param s the {@code LongSupplier} for generated elements
+ * @return a new sequential {@code LongStream}
+ */
+ public static LongStream generate(LongSupplier s) {
+ Objects.requireNonNull(s);
+ return StreamSupport.longStream(Spliterators.spliteratorUnknownSize(
+ new PrimitiveIterator.OfLong() {
+ @Override
+ public boolean hasNext() { return true; }
+
+ @Override
+ public long nextLong() { return s.getAsLong(); }
+ },
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL));
+ }
+
+ /**
+ * Returns a sequential {@code LongStream} from {@code startInclusive}
+ * (inclusive) to {@code endExclusive} (exclusive) by an incremental step of
+ * 1.
+ *
+ * @implSpec
+ * The implementation behaves as if:
+ * <pre>{@code
+ * longRange(startInclusive, endExclusive, 1);
+ * }</pre>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endExclusive the exclusive upper bound
+ * @return a sequential {@code LongStream} for the range of {@code long}
+ * elements
+ */
+ public static LongStream range(long startInclusive, final long endExclusive) {
+ return range(startInclusive, endExclusive, 1);
+ }
+
+ /**
+ * 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.
+ *
+ * <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) { ... }
+ * }</pre>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endExclusive the exclusive upper bound
+ * @param step the difference between consecutive values
+ * @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) {
+ return empty();
+ } else {
+ return StreamSupport.longStream(new Streams.RangeLongSpliterator(startInclusive, endExclusive, step));
+ }
+ }
}
--- a/jdk/src/share/classes/java/util/stream/Stream.java Mon Apr 29 18:12:28 2013 +0100
+++ b/jdk/src/share/classes/java/util/stream/Stream.java Sat Apr 20 18:53:26 2013 -0400
@@ -24,8 +24,13 @@
*/
package java.util.stream;
+import java.util.Arrays;
import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Objects;
import java.util.Optional;
+import java.util.Spliterator;
+import java.util.Spliterators;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
@@ -37,6 +42,7 @@
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
+import java.util.function.UnaryOperator;
// @@@ Specification to-do list @@@
// - Describe the difference between sequential and parallel streams
@@ -779,4 +785,109 @@
* @see #findFirst()
*/
Optional<T> findAny();
+
+ // Static factories
+
+ /**
+ * Returns a builder for a {@code Stream}.
+ *
+ * @param <T> type of elements
+ * @return a stream builder
+ */
+ public static<T> StreamBuilder<T> builder() {
+ return new Streams.StreamBuilderImpl<>();
+ }
+
+ /**
+ * Returns an empty sequential {@code Stream}.
+ *
+ * @param <T> the type of stream elements
+ * @return an empty sequential stream
+ */
+ public static<T> Stream<T> empty() {
+ return StreamSupport.stream(Spliterators.<T>emptySpliterator());
+ }
+
+ /**
+ * Returns a sequential {@code Stream} containing a single element.
+ *
+ * @param t the single element
+ * @param <T> the type of stream elements
+ * @return a singleton sequential stream
+ */
+ public static<T> Stream<T> of(T t) {
+ return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t));
+ }
+
+ /**
+ * Returns a sequential stream whose elements are the specified values.
+ *
+ * @param <T> the type of stream elements
+ * @param values the elements of the new stream
+ * @return the new stream
+ */
+ @SafeVarargs
+ public static<T> Stream<T> of(T... values) {
+ return Arrays.stream(values);
+ }
+
+ /**
+ * Returns an infinite sequential {@code Stream} produced by iterative
+ * application of a function {@code f} to an initial element {@code seed},
+ * producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
+ * {@code f(f(seed))}, etc.
+ *
+ * <p>The first element (position {@code 0}) in the {@code Stream} will be
+ * the provided {@code seed}. For {@code n > 0}, the element at position
+ * {@code n}, will be the result of applying the function {@code f} to the
+ * element at position {@code n - 1}.
+ *
+ * @param <T> the type of stream elements
+ * @param seed the initial element
+ * @param f a function to be applied to to the previous element to produce
+ * a new element
+ * @return a new sequential {@code Stream}
+ */
+ 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;
+
+ @Override
+ public boolean hasNext() {
+ return true;
+ }
+
+ @Override
+ public T next() {
+ return t = (t == Streams.NONE) ? seed : f.apply(t);
+ }
+ };
+ return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
+ iterator,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE));
+ }
+
+ /**
+ * Returns a sequential {@code Stream} where each element is
+ * generated by a {@code Supplier}. This is suitable for generating
+ * constant streams, streams of random elements, etc.
+ *
+ * @param <T> the type of stream elements
+ * @param s the {@code Supplier} of generated elements
+ * @return a new sequential {@code Stream}
+ */
+ public static<T> Stream<T> generate(Supplier<T> s) {
+ Objects.requireNonNull(s);
+ return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
+ new Iterator<T>() {
+ @Override
+ public boolean hasNext() { return true; }
+
+ @Override
+ public T next() { return s.get(); }
+ },
+ Spliterator.ORDERED | Spliterator.IMMUTABLE));
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/stream/StreamBuilder.java Sat Apr 20 18:53:26 2013 -0400
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 java.util.stream;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+/**
+ * A mutable builder for a {@code Stream}. This allows the creation of a
+ * {@code Stream} by generating elements individually and adding them to the
+ * {@code StreamBuilder} (without the copying overhead that comes from using
+ * an {@code ArrayList} as a temporary buffer.)
+ *
+ * <p>A {@code StreamBuilder} has a lifecycle, where it starts in a building
+ * phase, during which elements can be added, and then transitions to a built
+ * phase, after which elements may not be added. The built phase begins
+ * when the {@link #build()}} method is called, which creates an ordered
+ * {@code Stream} whose elements are the elements that were added to the stream
+ * builder, in the order they were added.
+ *
+ * <p>Primitive specializations of {@code StreamBuilder} are provided
+ * for {@link OfInt int}, {@link OfLong long}, and {@link OfDouble double}
+ * values.
+ *
+ * @param <T> the type of stream elements
+ * @see Stream#builder()
+ * @since 1.8
+ */
+public interface StreamBuilder<T> extends Consumer<T> {
+
+ /**
+ * Adds an element to the stream being built.
+ *
+ * @throws IllegalStateException if the builder has already transitioned to
+ * the built state
+ */
+ @Override
+ void accept(T t);
+
+ /**
+ * Adds an element to the stream being built.
+ *
+ * @implSpec
+ * The default implementation behaves as if:
+ * <pre>{@code
+ * accept(t)
+ * return this;
+ * }</pre>
+ *
+ * @param t the element to add
+ * @return {@code this} builder
+ * @throws IllegalStateException if the builder has already transitioned to
+ * the built state
+ */
+ default StreamBuilder<T> add(T t) {
+ accept(t);
+ return this;
+ }
+
+ /**
+ * Builds the stream, transitioning this builder to the built state.
+ * An {@code IllegalStateException} is thrown if there are further attempts
+ * to operate on the builder after it has entered the built state.
+ *
+ * @return the built stream
+ * @throws IllegalStateException if the builder has already transitioned to
+ * the built state
+ */
+ Stream<T> build();
+
+ /**
+ * A mutable builder for an {@code IntStream}.
+ *
+ * <p>A stream builder has a lifecycle, where it starts in a building
+ * phase, during which elements can be added, and then transitions to a
+ * built phase, after which elements may not be added. The built phase
+ * begins when the {@link #build()}} method is called, which creates an
+ * ordered stream whose elements are the elements that were added to the
+ * stream builder, in the order they were added.
+ *
+ * @see IntStream#builder()
+ * @since 1.8
+ */
+ interface OfInt extends IntConsumer {
+
+ /**
+ * Adds an element to the stream being built.
+ *
+ * @throws IllegalStateException if the builder has already transitioned
+ * to the built state
+ */
+ @Override
+ void accept(int t);
+
+ /**
+ * Adds an element to the stream being built.
+ *
+ * @implSpec
+ * The default implementation behaves as if:
+ * <pre>{@code
+ * accept(t)
+ * return this;
+ * }</pre>
+ *
+ * @param t the element to add
+ * @return {@code this} builder
+ * @throws IllegalStateException if the builder has already transitioned
+ * to the built state
+ */
+ default StreamBuilder.OfInt add(int t) {
+ accept(t);
+ return this;
+ }
+
+ /**
+ * Builds the stream, transitioning this builder to the built state.
+ * An {@code IllegalStateException} is thrown if there are further
+ * attempts to operate on the builder after it has entered the built
+ * state.
+ *
+ * @return the built stream
+ * @throws IllegalStateException if the builder has already transitioned to
+ * the built state
+ */
+ IntStream build();
+ }
+
+ /**
+ * A mutable builder for a {@code LongStream}.
+ *
+ * <p>A stream builder has a lifecycle, where it starts in a building
+ * phase, during which elements can be added, and then transitions to a
+ * built phase, after which elements may not be added. The built phase
+ * begins when the {@link #build()}} method is called, which creates an
+ * ordered stream whose elements are the elements that were added to the
+ * stream builder, in the order they were added.
+ *
+ * @see LongStream#builder()
+ * @since 1.8
+ */
+ interface OfLong extends LongConsumer {
+
+ /**
+ * Adds an element to the stream being built.
+ *
+ * @throws IllegalStateException if the builder has already transitioned
+ * to the built state
+ */
+ @Override
+ void accept(long t);
+
+ /**
+ * Adds an element to the stream being built.
+ *
+ * @implSpec
+ * The default implementation behaves as if:
+ * <pre>{@code
+ * accept(t)
+ * return this;
+ * }</pre>
+ *
+ * @param t the element to add
+ * @return {@code this} builder
+ * @throws IllegalStateException if the builder has already transitioned
+ * to the built state
+ */
+ default StreamBuilder.OfLong add(long t) {
+ accept(t);
+ return this;
+ }
+
+ /**
+ * Builds the stream, transitioning this builder to the built state.
+ * An {@code IllegalStateException} is thrown if there are further
+ * attempts to operate on the builder after it has entered the built
+ * state.
+ *
+ * @return the built stream
+ * @throws IllegalStateException if the builder has already transitioned
+ * to the built state
+ */
+ LongStream build();
+ }
+
+ /**
+ * A mutable builder for a {@code DoubleStream}.
+ *
+ * @see LongStream#builder()
+ * @since 1.8
+ */
+ interface OfDouble extends DoubleConsumer {
+
+ /**
+ * Adds an element to the stream being built.
+ *
+ * <p>A stream builder has a lifecycle, where it starts in a building
+ * phase, during which elements can be added, and then transitions to a
+ * built phase, after which elements may not be added. The built phase
+ * begins when the {@link #build()}} method is called, which creates an
+ * ordered stream whose elements are the elements that were added to the
+ * stream builder, in the order they were added.
+ *
+ * @throws IllegalStateException if the builder has already transitioned
+ * to the built state
+ */
+ @Override
+ void accept(double t);
+
+ /**
+ * Adds an element to the stream being built.
+ *
+ * @implSpec
+ * The default implementation behaves as if:
+ * <pre>{@code
+ * accept(t)
+ * return this;
+ * }</pre>
+ *
+ * @param t the element to add
+ * @return {@code this} builder
+ * @throws IllegalStateException if the builder has already transitioned
+ * to the built state
+ */
+ default StreamBuilder.OfDouble add(double t) {
+ accept(t);
+ return this;
+ }
+
+ /**
+ * Builds the stream, transitioning this builder to the built state.
+ * An {@code IllegalStateException} is thrown if there are further
+ * attempts to operate on the builder after it has entered the built
+ * state.
+ *
+ * @return the built stream
+ * @throws IllegalStateException if the builder has already transitioned
+ * to the built state
+ */
+ DoubleStream build();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/stream/Streams.java Sat Apr 20 18:53:26 2013 -0400
@@ -0,0 +1,656 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 java.util.stream;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+/**
+ * Utility methods for operating on and creating streams.
+ *
+ * <p>Unless otherwise stated, streams are created as sequential streams. A
+ * sequential stream can be transformed into a parallel stream by calling the
+ * {@code parallel()} method on the created stream.
+ *
+ * @since 1.8
+ */
+class Streams {
+
+ private Streams() {
+ throw new Error("no instances");
+ }
+
+ /**
+ * 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 {
+ private int from;
+ private final int upTo;
+ private final int step;
+
+ RangeIntSpliterator(int from, int upTo, int step) {
+ this.from = from;
+ this.upTo = upTo;
+ this.step = step;
+ }
+
+ @Override
+ public boolean tryAdvance(IntConsumer consumer) {
+ boolean hasNext = from < upTo;
+ if (hasNext) {
+ consumer.accept(from);
+ from += step;
+ }
+ return hasNext;
+ }
+
+ @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);
+ from = upTo;
+ }
+
+ @Override
+ public long estimateSize() {
+ int d = upTo - from;
+ return (d / step) + ((d % step == 0) ? 0 : 1);
+ }
+
+ @Override
+ public int characteristics() {
+ return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED |
+ Spliterator.IMMUTABLE | Spliterator.NONNULL |
+ Spliterator.DISTINCT | Spliterator.SORTED;
+ }
+
+ @Override
+ public Comparator<? super Integer> getComparator() {
+ return null;
+ }
+
+ @Override
+ public Spliterator.OfInt trySplit() {
+ return estimateSize() <= 1
+ ? null
+ : new RangeIntSpliterator(from, from = from + midPoint(), step);
+ }
+
+ 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;
+ }
+ }
+
+ /**
+ * A {@code long} range spliterator.
+ */
+ static final class RangeLongSpliterator implements Spliterator.OfLong {
+ private long from;
+ private final long upTo;
+ private final long step;
+
+ RangeLongSpliterator(long from, long upTo, long step) {
+ this.from = from;
+ this.upTo = upTo;
+ this.step = step;
+ }
+
+ @Override
+ public boolean tryAdvance(LongConsumer consumer) {
+ boolean hasNext = from < upTo;
+ if (hasNext) {
+ consumer.accept(from);
+ from += step;
+ }
+ return hasNext;
+ }
+
+ @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);
+ from = upTo;
+ }
+
+ @Override
+ public long estimateSize() {
+ long d = upTo - from;
+ return (d / step) + ((d % step == 0) ? 0 : 1);
+ }
+
+ @Override
+ public int characteristics() {
+ return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED |
+ Spliterator.IMMUTABLE | Spliterator.NONNULL |
+ Spliterator.DISTINCT | Spliterator.SORTED;
+ }
+
+ @Override
+ public Comparator<? super Long> getComparator() {
+ return null;
+ }
+
+ @Override
+ public Spliterator.OfLong trySplit() {
+ return estimateSize() <= 1
+ ? null
+ : new RangeLongSpliterator(from, from = from + midPoint(), step);
+ }
+
+ 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;
+ }
+ }
+
+ /**
+ * A {@code double} range spliterator.
+ *
+ * <p>The traversing and splitting logic is equivalent to that of
+ * {@code RangeLongSpliterator} for increasing values with a {@code step} of
+ * {@code 1}.
+ *
+ * <p>A {@code double} value is calculated from the function
+ * {@code start + i * step} where {@code i} is the absolute position of the
+ * value when traversing an instance of this class that has not been split.
+ * This ensures the same values are produced at the same absolute positions
+ * regardless of how an instance of this class is split or traversed.
+ */
+ static final class RangeDoubleSpliterator implements Spliterator.OfDouble {
+ private final double from;
+ private final double upTo;
+ private final double step;
+
+ private long lFrom;
+ private final long lUpTo;
+
+ RangeDoubleSpliterator(double from, double upTo, double step, long lFrom, long lUpTo) {
+ this.from = from;
+ this.upTo = upTo;
+ this.step = step;
+ this.lFrom = lFrom;
+ this.lUpTo = lUpTo;
+ }
+
+ @Override
+ public boolean tryAdvance(DoubleConsumer consumer) {
+ boolean hasNext = lFrom < lUpTo;
+ if (hasNext) {
+ consumer.accept(from + lFrom * step);
+ lFrom++;
+ }
+ return hasNext;
+ }
+
+ @Override
+ public void forEachRemaining(DoubleConsumer consumer) {
+ double hOrigin = from;
+ double hStep = step;
+ long hLUpTo = lUpTo;
+ long i = lFrom;
+ for (; i < hLUpTo; i++) {
+ consumer.accept(hOrigin + i * hStep);
+ }
+ lFrom = i;
+ }
+
+ @Override
+ public long estimateSize() {
+ return lUpTo - lFrom;
+ }
+
+ @Override
+ public int characteristics() {
+ return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED |
+ Spliterator.IMMUTABLE | Spliterator.NONNULL |
+ Spliterator.DISTINCT | Spliterator.SORTED;
+ }
+
+ @Override
+ public Comparator<? super Double> getComparator() {
+ return null;
+ }
+
+ @Override
+ public Spliterator.OfDouble trySplit() {
+ return estimateSize() <= 1
+ ? null
+ : new RangeDoubleSpliterator(from, upTo, step, lFrom, lFrom = lFrom + midPoint());
+ }
+
+ private long midPoint() {
+ // Size is known to be >= 2
+ return (lUpTo - lFrom) / 2;
+ }
+ }
+
+ private static abstract class AbstractStreamBuilderImpl<T, S extends Spliterator<T>> implements Spliterator<T> {
+ // >= 0 when building, < 0 when built
+ // -1 == no elements
+ // -2 == one element, held by first
+ // -3 == two or more elements, held by buffer
+ int count;
+
+ // Spliterator implementation for 0 or 1 element
+ // count == -1 for no elements
+ // count == -2 for one element held by first
+
+ @Override
+ public S trySplit() {
+ return null;
+ }
+
+ @Override
+ public long estimateSize() {
+ return -count - 1;
+ }
+
+ @Override
+ public int characteristics() {
+ return Spliterator.SIZED | Spliterator.SUBSIZED |
+ Spliterator.ORDERED | Spliterator.IMMUTABLE;
+ }
+ }
+
+ static final class StreamBuilderImpl<T>
+ extends AbstractStreamBuilderImpl<T, Spliterator<T>>
+ implements StreamBuilder<T> {
+ // The first element in the stream
+ // valid if count == 1
+ T first;
+
+ // The first and subsequent elements in the stream
+ // non-null if count == 2
+ SpinedBuffer<T> buffer;
+
+ /**
+ * Constructor for building a stream of 0 or more elements.
+ */
+ StreamBuilderImpl() { }
+
+ /**
+ * Constructor for a singleton stream.
+ *
+ * @param t the single element
+ */
+ StreamBuilderImpl(T t) {
+ first = t;
+ count = -2;
+ }
+
+ // StreamBuilder implementation
+
+ @Override
+ public void accept(T t) {
+ if (count == 0) {
+ first = t;
+ count++;
+ }
+ else if (count > 0) {
+ if (buffer == null) {
+ buffer = new SpinedBuffer<>();
+ buffer.accept(first);
+ count++;
+ }
+
+ buffer.accept(t);
+ }
+ else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public StreamBuilder<T> add(T t) {
+ accept(t);
+ return this;
+ }
+
+ @Override
+ public Stream<T> build() {
+ int c = count;
+ if (c >= 0) {
+ // Switch count to negative value signalling the builder is built
+ count = -count - 1;
+ // Use this spliterator if 0 or 1 elements, otherwise use
+ // the spliterator of the spined buffer
+ return (c < 2) ? StreamSupport.stream(this) : StreamSupport.stream(buffer.spliterator());
+ }
+
+ throw new IllegalStateException();
+ }
+
+ // Spliterator implementation for 0 or 1 element
+ // count == -1 for no elements
+ // count == -2 for one element held by first
+
+ @Override
+ public boolean tryAdvance(Consumer<? super T> action) {
+ if (count == -2) {
+ action.accept(first);
+ count = -1;
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ @Override
+ public void forEachRemaining(Consumer<? super T> action) {
+ if (count == -2) {
+ action.accept(first);
+ count = -1;
+ }
+ }
+ }
+
+ static final class IntStreamBuilderImpl
+ extends AbstractStreamBuilderImpl<Integer, Spliterator.OfInt>
+ implements StreamBuilder.OfInt, Spliterator.OfInt {
+ // The first element in the stream
+ // valid if count == 1
+ int first;
+
+ // The first and subsequent elements in the stream
+ // non-null if count == 2
+ SpinedBuffer.OfInt buffer;
+
+ /**
+ * Constructor for building a stream of 0 or more elements.
+ */
+ IntStreamBuilderImpl() { }
+
+ /**
+ * Constructor for a singleton stream.
+ *
+ * @param t the single element
+ */
+ IntStreamBuilderImpl(int t) {
+ first = t;
+ count = -2;
+ }
+
+ // StreamBuilder implementation
+
+ @Override
+ public void accept(int t) {
+ if (count == 0) {
+ first = t;
+ count++;
+ }
+ else if (count > 0) {
+ if (buffer == null) {
+ buffer = new SpinedBuffer.OfInt();
+ buffer.accept(first);
+ count++;
+ }
+
+ buffer.accept(t);
+ }
+ else {
+ throw new IllegalStateException();
+ }
+ }
+
+ @Override
+ public IntStream build() {
+ int c = count;
+ if (c >= 0) {
+ // Switch count to negative value signalling the builder is built
+ count = -count - 1;
+ // Use this spliterator if 0 or 1 elements, otherwise use
+ // the spliterator of the spined buffer
+ return (c < 2) ? StreamSupport.intStream(this) : StreamSupport.intStream(buffer.spliterator());
+ }
+
+ throw new IllegalStateException();
+ }
+
+ // Spliterator implementation for 0 or 1 element
+ // count == -1 for no elements
+ // count == -2 for one element held by first
+
+ @Override
+ public boolean tryAdvance(IntConsumer action) {
+ if (count == -2) {
+ action.accept(first);
+ count = -1;
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ @Override
+ public void forEachRemaining(IntConsumer action) {
+ if (count == -2) {
+ action.accept(first);
+ count = -1;
+ }
+ }
+ }
+
+ static final class LongStreamBuilderImpl
+ extends AbstractStreamBuilderImpl<Long, Spliterator.OfLong>
+ implements StreamBuilder.OfLong, Spliterator.OfLong {
+ // The first element in the stream
+ // valid if count == 1
+ long first;
+
+ // The first and subsequent elements in the stream
+ // non-null if count == 2
+ SpinedBuffer.OfLong buffer;
+
+ /**
+ * Constructor for building a stream of 0 or more elements.
+ */
+ LongStreamBuilderImpl() { }
+
+ /**
+ * Constructor for a singleton stream.
+ *
+ * @param t the single element
+ */
+ LongStreamBuilderImpl(long t) {
+ first = t;
+ count = -2;
+ }
+
+ // StreamBuilder implementation
+
+ @Override
+ public void accept(long t) {
+ if (count == 0) {
+ first = t;
+ count++;
+ }
+ else if (count > 0) {
+ if (buffer == null) {
+ buffer = new SpinedBuffer.OfLong();
+ buffer.accept(first);
+ count++;
+ }
+
+ buffer.accept(t);
+ }
+ else {
+ throw new IllegalStateException();
+ }
+ }
+
+ @Override
+ public LongStream build() {
+ int c = count;
+ if (c >= 0) {
+ // Switch count to negative value signalling the builder is built
+ count = -count - 1;
+ // Use this spliterator if 0 or 1 elements, otherwise use
+ // the spliterator of the spined buffer
+ return (c < 2) ? StreamSupport.longStream(this) : StreamSupport.longStream(buffer.spliterator());
+ }
+
+ throw new IllegalStateException();
+ }
+
+ // Spliterator implementation for 0 or 1 element
+ // count == -1 for no elements
+ // count == -2 for one element held by first
+
+ @Override
+ public boolean tryAdvance(LongConsumer action) {
+ if (count == -2) {
+ action.accept(first);
+ count = -1;
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ @Override
+ public void forEachRemaining(LongConsumer action) {
+ if (count == -2) {
+ action.accept(first);
+ count = -1;
+ }
+ }
+ }
+
+ static final class DoubleStreamBuilderImpl
+ extends AbstractStreamBuilderImpl<Double, Spliterator.OfDouble>
+ implements StreamBuilder.OfDouble, Spliterator.OfDouble {
+ // The first element in the stream
+ // valid if count == 1
+ double first;
+
+ // The first and subsequent elements in the stream
+ // non-null if count == 2
+ SpinedBuffer.OfDouble buffer;
+
+ /**
+ * Constructor for building a stream of 0 or more elements.
+ */
+ DoubleStreamBuilderImpl() { }
+
+ /**
+ * Constructor for a singleton stream.
+ *
+ * @param t the single element
+ */
+ DoubleStreamBuilderImpl(double t) {
+ first = t;
+ count = -2;
+ }
+
+ // StreamBuilder implementation
+
+ @Override
+ public void accept(double t) {
+ if (count == 0) {
+ first = t;
+ count++;
+ }
+ else if (count > 0) {
+ if (buffer == null) {
+ buffer = new SpinedBuffer.OfDouble();
+ buffer.accept(first);
+ count++;
+ }
+
+ buffer.accept(t);
+ }
+ else {
+ throw new IllegalStateException();
+ }
+ }
+
+ @Override
+ public DoubleStream build() {
+ int c = count;
+ if (c >= 0) {
+ // Switch count to negative value signalling the builder is built
+ count = -count - 1;
+ // Use this spliterator if 0 or 1 elements, otherwise use
+ // the spliterator of the spined buffer
+ return (c < 2) ? StreamSupport.doubleStream(this) : StreamSupport.doubleStream(buffer.spliterator());
+ }
+
+ throw new IllegalStateException();
+ }
+
+ // Spliterator implementation for 0 or 1 element
+ // count == -1 for no elements
+ // count == -2 for one element held by first
+
+ @Override
+ public boolean tryAdvance(DoubleConsumer action) {
+ if (count == -2) {
+ action.accept(first);
+ count = -1;
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ @Override
+ public void forEachRemaining(DoubleConsumer action) {
+ if (count == -2) {
+ action.accept(first);
+ count = -1;
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Arrays/SetAllTest.java Sat Apr 20 18:53:26 2013 -0400
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8012650
+ * @summary Unit test for setAll, parallelSetAll variants
+ * @run testng SetAllTest
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.function.IntFunction;
+import java.util.function.IntToDoubleFunction;
+import java.util.function.IntToLongFunction;
+import java.util.function.IntUnaryOperator;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.fail;
+
+@Test
+public class SetAllTest {
+ private static final IntFunction<String> toString = i -> "N" + Integer.valueOf(i);
+ private static final IntFunction<String> fillString = i -> "X";
+ private static final String[] r0 = {};
+ private static final String[] r1 = { "N0" };
+ private static final String[] r10 = { "N0", "N1", "N2", "N3", "N4", "N5", "N6", "N7", "N8", "N9" };
+
+ private Object[][] stringData = new Object[][] {
+ { "empty", 0, toString, r0 },
+ { "one", 1, toString, r1 },
+ { "ten", 10, toString, r10 },
+ { "fill", 3, fillString, new String[] { "X", "X", "X" }}
+ };
+
+ private static final IntUnaryOperator toInt = i -> i << 1;
+ private static final IntUnaryOperator fillInt = i -> 99;
+ private static final int[] ir0 = {};
+ private static final int[] ir1 = { 0 };
+ private static final int[] ir10 = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 };
+ private Object[][] intData = new Object[][] {
+ { "empty", 0, toInt, ir0 },
+ { "one", 1, toInt, ir1 },
+ { "ten", 10, toInt, ir10 },
+ { "fill", 3, fillInt, new int[] { 99, 99, 99 }}
+ };
+
+ private static final IntToLongFunction toLong = i -> i << 1;
+ private static final IntToLongFunction fillLong = i -> 9999L;
+ private static final long[] lr0 = {};
+ private static final long[] lr1 = { 0L };
+ private static final long[] lr10 = { 0L, 2L, 4L, 6L, 8L, 10L, 12L, 14L, 16L, 18L };
+ private Object[][] longData = new Object[][] {
+ { "empty", 0, toLong, lr0 },
+ { "one", 1, toLong, lr1 },
+ { "ten", 10, toLong, lr10 },
+ { "fill", 3, fillLong, new long[] { 9999L, 9999L, 9999L }}
+ };
+
+ private static final IntToDoubleFunction toDouble = i -> i * 1.1;
+ private static final IntToDoubleFunction fillDouble = i -> 3.14;
+ private static final double[] dr0 = {};
+ private static final double[] dr1 = { 0.0 };
+ private static final double[] dr10 = { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };
+ private Object[][] doubleData = new Object[][] {
+ { "empty", 0, toDouble, dr0 },
+ { "one", 1, toDouble, dr1 },
+ { "ten", 10, toDouble, dr10 },
+ { "fill", 3, fillDouble, new double[] { 3.14, 3.14, 3.14 }}
+ };
+
+ @DataProvider(name="string")
+ public Object[][] stringTests() { return stringData; }
+
+ @DataProvider(name="int")
+ public Object[][] intTests() { return intData; }
+
+ @DataProvider(name="long")
+ public Object[][] longTests() { return longData; }
+
+ @DataProvider(name="double")
+ public Object[][] doubleTests() { return doubleData; }
+
+ @Test(dataProvider = "string")
+ public void testSetAllString(String name, int size, IntFunction<String> generator, String[] expected) {
+ String[] result = new String[size];
+ Arrays.setAll(result, generator);
+ assertEquals(result, expected, "setAll(String[], IntFunction<String>) case " + name + " failed.");
+
+ // ensure fresh array
+ result = new String[size];
+ Arrays.parallelSetAll(result, generator);
+ assertEquals(result, expected, "parallelSetAll(String[], IntFunction<String>) case " + name + " failed.");
+ }
+
+ @Test(dataProvider = "int")
+ public void testSetAllInt(String name, int size, IntUnaryOperator generator, int[] expected) {
+ int[] result = new int[size];
+ Arrays.setAll(result, generator);
+ assertEquals(result, expected, "setAll(int[], IntUnaryOperator) case " + name + " failed.");
+
+ // ensure fresh array
+ result = new int[size];
+ Arrays.parallelSetAll(result, generator);
+ assertEquals(result, expected, "parallelSetAll(int[], IntUnaryOperator) case " + name + " failed.");
+ }
+
+ @Test(dataProvider = "long")
+ public void testSetAllLong(String name, int size, IntToLongFunction generator, long[] expected) {
+ long[] result = new long[size];
+ Arrays.setAll(result, generator);
+ assertEquals(result, expected, "setAll(long[], IntToLongFunction) case " + name + " failed.");
+
+ // ensure fresh array
+ result = new long[size];
+ Arrays.parallelSetAll(result, generator);
+ assertEquals(result, expected, "parallelSetAll(long[], IntToLongFunction) case " + name + " failed.");
+ }
+
+ private void assertDoubleArrayEquals(double[] actual, double[] expected, double delta, String msg) {
+ if (actual.length != expected.length) {
+ fail(msg + ": length mismatch, expected " + expected.length + ", got " + actual.length);
+ }
+
+ for (int i = 0; i < actual.length; i++) {
+ assertEquals(actual[i], expected[i], delta, msg + "(mismatch at index " + i + ")");
+ }
+ }
+
+ @Test(dataProvider = "double")
+ public void testSetAllDouble(String name, int size, IntToDoubleFunction generator, double[] expected) {
+ double[] result = new double[size];
+ Arrays.setAll(result, generator);
+ assertDoubleArrayEquals(result, expected, 0.05, "setAll(double[], IntToDoubleFunction) case " + name + " failed.");
+
+ // ensure fresh array
+ result = new double[size];
+ Arrays.parallelSetAll(result, generator);
+ assertDoubleArrayEquals(result, expected, 0.05, "setAll(double[], IntToDoubleFunction) case " + name + " failed.");
+ }
+
+ @Test
+ public void testStringSetNulls() {
+ String[] ar = new String[2];
+ try {
+ Arrays.setAll(null, i -> "X");
+ fail("Arrays.setAll(null, foo) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ try {
+ Arrays.parallelSetAll(null, i -> "X");
+ fail("Arrays.parallelSetAll(null, foo) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ try {
+ Arrays.setAll(ar, null);
+ fail("Arrays.setAll(array, null) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ try {
+ Arrays.parallelSetAll(ar, null);
+ fail("Arrays.parallelSetAll(array, null) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testIntSetNulls() {
+ int[] ar = new int[2];
+ try {
+ Arrays.setAll(null, (IntUnaryOperator) i -> i);
+ fail("Arrays.setAll(null, foo) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ try {
+ Arrays.parallelSetAll(null, (IntUnaryOperator) i -> i);
+ fail("Arrays.parallelSetAll(null, foo) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ try {
+ Arrays.setAll(ar, null);
+ fail("Arrays.setAll(array, null) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ try {
+ Arrays.parallelSetAll(ar, null);
+ fail("Arrays.parallelSetAll(array, null) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testLongSetNulls() {
+ long[] ar = new long[2];
+ try {
+ Arrays.setAll(null, (IntToLongFunction) i -> Long.MAX_VALUE);
+ fail("Arrays.setAll(null, foo) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ try {
+ Arrays.parallelSetAll(null, (IntToLongFunction) i -> Long.MAX_VALUE);
+ fail("Arrays.parallelSetAll(null, foo) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ try {
+ Arrays.setAll(ar, null);
+ fail("Arrays.setAll(array, null) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ try {
+ Arrays.parallelSetAll(ar, null);
+ fail("Arrays.parallelSetAll(array, null) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testDoubleSetNulls() {
+ double[] ar = new double[2];
+ try {
+ Arrays.setAll(null, (IntToDoubleFunction) i -> Math.E);
+ fail("Arrays.setAll(null, foo) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ try {
+ Arrays.parallelSetAll(null, (IntToDoubleFunction) i -> Math.E);
+ fail("Arrays.parallelSetAll(null, foo) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ try {
+ Arrays.setAll(ar, null);
+ fail("Arrays.setAll(array, null) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ try {
+ Arrays.parallelSetAll(ar, null);
+ fail("Arrays.parallelSetAll(array, null) should throw NPE");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ }
+}
\ No newline at end of file