Proposal: Stream.iterateWhile(T seed, Function<T, Optional<T>> mapper)
Tomasz Linkowski
t.linkowski at gmail.com
Fri Oct 26 15:44:36 UTC 2018
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
More information about the core-libs-dev
mailing list