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

Reply via email to