src/share/classes/java/util/stream/DoubleStream.java

Print this page
rev 6980 : [mq]: 7b.JDK-8011918
rev 6981 : [mq]: range

*** 22,40 **** --- 22,44 ---- * or visit www.oracle.com if you need additional information or have any * questions. */ 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; import java.util.function.Function; import java.util.function.ObjDoubleConsumer;
*** 647,652 **** --- 651,825 ---- @Override PrimitiveIterator.OfDouble iterator(); @Override Spliterator.OfDouble spliterator(); + + + // Static factories + + /** + * Returns a builder for a {@code DoubleStream}. + * + * @return the 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 The 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 a 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 {@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 a range of {@code double} + * elements + * @throws IllegalArgumentException + * if {@code step} is less than or equal to 0, + * or the or the count of elements in the range would be greater + * than {@code Long.MAX_VALUE} or is {@code NaN}. + */ + 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 if (startInclusive > endExclusive) + return empty(); + else { + 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)); + } + } }