8164691: Stream specification clarifications for iterate and collect

Reviewed-by: briangoetz, smarks, tvaleev
This commit is contained in:
Paul Sandoz 2016-09-09 14:54:29 -07:00
parent caa7db4496
commit a7dd7b59da
4 changed files with 191 additions and 123 deletions

View file

@ -562,19 +562,23 @@ public interface IntStream extends BaseStream<Integer, IntStream> {
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
* @param <R> type of the result
* @param supplier a function that creates a new result container. For a
* parallel execution, this function may be called
* @param <R> the type of the mutable result container
* @param supplier a function that creates a new mutable result container.
* For a parallel execution, this function may be called
* multiple times and must return a fresh value each time.
* @param accumulator an <a href="package-summary.html#Associativity">associative</a>,
* <a href="package-summary.html#NonInterference">non-interfering</a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function for incorporating an additional element into a result
* function that must fold an element into a result
* container.
* @param combiner an <a href="package-summary.html#Associativity">associative</a>,
* <a href="package-summary.html#NonInterference">non-interfering</a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function for combining two values, which must be
* compatible with the accumulator function
* function that accepts two partial result containers
* and merges them, which must be compatible with the
* accumulator function. The combiner function must fold
* the elements from the second result container into the
* first result container.
* @return the result of the reduction
* @see Stream#collect(Supplier, BiConsumer, BiConsumer)
*/
@ -887,6 +891,12 @@ public interface IntStream extends BaseStream<Integer, IntStream> {
* {@code n}, will be the result of applying the function {@code f} to the
* element at position {@code n - 1}.
*
* <p>The action of applying {@code f} for one element
* <a href="../concurrent/package-summary.html#MemoryVisibility"><i>happens-before</i></a>
* the action of applying {@code f} for subsequent elements. For any given
* element the action may be performed in whatever thread the library
* chooses.
*
* @param seed the initial element
* @param f a function to be applied to the previous element to produce
* a new element
@ -918,37 +928,44 @@ public interface IntStream extends BaseStream<Integer, IntStream> {
/**
* 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.
* application of the given {@code next} function to an initial element,
* conditioned on satisfying the given {@code hasNext} predicate. The
* stream terminates as soon as the {@code hasNext} predicate returns false.
*
* <p>
* {@code IntStream.iterate} should produce the same sequence of elements
* as produced by the corresponding for-loop:
* <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.applyAsInt(index)) {
* for (int index=seed; hasNext.test(index); index = next.applyAsInt(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.
* <p>The resulting sequence may be empty if the {@code hasNext} predicate
* does not hold on the seed value. Otherwise the first element will be the
* supplied {@code seed} value, the next element (if present) will be the
* result of applying the {@code next} function to the {@code seed} value,
* and so on iteratively until the {@code hasNext} predicate indicates that
* the stream should terminate.
*
* <p>The action of applying the {@code hasNext} predicate to an element
* <a href="../concurrent/package-summary.html#MemoryVisibility"><i>happens-before</i></a>
* the action of applying the {@code next} function to that element. The
* action of applying the {@code next} function for one element
* <i>happens-before</i> the action of applying the {@code hasNext}
* predicate for subsequent elements. For any given element an action may
* be performed in whatever thread the library chooses.
*
* @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
* @param hasNext a predicate to apply to elements to determine when the
* stream must terminate.
* @param next 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);
public static IntStream iterate(int seed, IntPredicate hasNext, IntUnaryOperator next) {
Objects.requireNonNull(next);
Objects.requireNonNull(hasNext);
Spliterator.OfInt spliterator = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE,
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
int prev;
@ -961,12 +978,12 @@ public interface IntStream extends BaseStream<Integer, IntStream> {
return false;
int t;
if (started)
t = f.applyAsInt(prev);
t = next.applyAsInt(prev);
else {
t = seed;
started = true;
}
if (!predicate.test(t)) {
if (!hasNext.test(t)) {
finished = true;
return false;
}
@ -980,10 +997,10 @@ public interface IntStream extends BaseStream<Integer, IntStream> {
if (finished)
return;
finished = true;
int t = started ? f.applyAsInt(prev) : seed;
while (predicate.test(t)) {
int t = started ? next.applyAsInt(prev) : seed;
while (hasNext.test(t)) {
action.accept(t);
t = f.applyAsInt(t);
t = next.applyAsInt(t);
}
}
};