<T> Stream.fromForEach(Consumer<Consumer<T>>)

Tagir Valeev amaembo at gmail.com
Mon May 23 06:01:44 UTC 2022


Hello!

There's a Stream.builder for this purpose:

var builder = Stream.<String>builder();
new Parser("1 2 3").parse(builder);
builder.build().forEach(System.out::println);

A little bit more verbose than your suggestion but this way it's more
clear that the whole stream content will be buffered.

With best regards,
Tagir Valeev

On Sun, May 22, 2022 at 5:54 AM Remi Forax <forax at univ-mlv.fr> wrote:
>
> Hi all,
> a stream is kind of push iterator so it can be created from any object that has a method like forEach(Consumer),
> but sadly there is no static method to create a Stream from a Consumer of Consumer so people usually miss that creating a Stream from events pushed to a consumer is easy.
>
> By example, let say i've a very simple parser like this, it calls the listener/callback for each tokens
>
>   record Parser(String text) {
>     void parse(Consumer<? super String> listener) {
>       for(var token: text.split(" ")) {
>          listener.accept(token);
>       }
>     }
>   }
>
> Using the method Stream.fromForEach, we can create a Stream from the sequence of tokens that are pushed through the listener
>   var parser = new Parser("1 2");
>   var stream = Stream.fromForEach(parser::parse);
>
> It can also works with an iterable, an optional or even a collection
>   Iterable<String> iterable = ...
>   var stream = Stream.fromForEach(iterable::forEachRemaning);
>
>   Optional<String> optional = ...
>   var stream = Stream.fromForEach(optional::ifPresent);
>
>   List<String> list = ...
>   var stream = Stream.fromForEach(list::forEach);
>
> I known the last two examples already have their own method stream(), it's just to explain how Stream.fromForEach is supposed to work.
>
> In term of implementation, Stream.fromForEach() is equivalent to creating a stream using a mapMulti(), so it can be implemented like this
>
>   static <T> Stream<T> fromForEach(Consumer<? super Consumer<T>> forEach) {
>     return Stream.of((T) null).mapMulti((__, consumer) -> forEach.accept(consumer));
>   }
>
> but i think that Stream.fromForEach(iterable::forEachRemaning) is more readable than Stream.of(iterable).mapMult(Iterable::forEachRemaining).
>
> The name fromForEach is not great and i'm sure someone will come with a better one.
>
> regards,
> Rémi


More information about the core-libs-dev mailing list