Hi, Please, consider adding a new static method to the `Stream` interface (names TBD):
static <T> Stream<T> iterateWhile( T seed, Function<? super T, ? extends Optional<? extends T>> mapper ); == OVERVIEW == + non-null equivalent of `Stream.iterate(seed, hasNext, next)` [1] + `mapper` like in `Optional.flatMap(mapper)` [2] + shift from two operations to one operation, like in: - `Iterator.hasNext/next` => `Spliterator.tryAdvance` - pattern matching (test/bind) + intent: "nudge towards writing clearer code" (Brian Goetz about LVTI [3]) + useful for `Optional`-based APIs + trivial implementation == JUSTIFICATION == `Stream.iterate(seed, hasNext, next)` is great for nullable-return-based APIs. Example: returning a chain of `Throwable` causes: Stream.iterate(throwable, Objects::nonNull, Throwable::getCause) For `Optional`-based APIs, using `Stream.iterate` becomes cumbersome. Example (assume `Throwable.findCause()` returns `Optional`): Stream.iterate(throwable, Objects::nonNull, t -> t.findCause().orElse(null)) Using the proposed method, the above can become much clearer: Stream.iterateWhile(throwable, Throwable::findCause) This is just one example - I can provide more if needed. == IMPLEMENTATION == Preferred implementation: iterateWhile(seed, mapper) -> Stream.iterate( seed, Objects::nonNull, t -> mapper.apply(t).orElse(null) ); Equivalent `Optional`-based implementation: iterateWhile(seed, mapper) -> Stream.iterate( Optional.ofNullable(seed), Optional::isPresent, optional -> optional.flatMap(mapper) ).map(Optional::get); Note that both implementations assume that `null` seed yields an empty `Stream`. == NAMING == Name `iterate` cannot be safely overloaded because of `Stream.iterate(UnaryOperator)` so another name needs to be used. I proposed `iterateWhile` inspired by `takeWhile` but maybe it's a wrong trail (`takeWhile` takes a `Predicate`). Other names that come to my mind: `iterateWhilePresent`, `iterateOptional`, `iterateNonNull`. [1] https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Stream.html#iterate(T,java.util.function.Predicate,java.util.function.UnaryOperator) [2] https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Optional.html#flatMap(java.util.function.Function) [3] http://mail.openjdk.java.net/pipermail/amber-spec-experts/2018-October/000826.html -- Regards, Tomasz Linkowski