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