----- Original Message -----
> From: "Tagir Valeev" <amae...@gmail.com>
> To: "Remi Forax" <fo...@univ-mlv.fr>
> Cc: "core-libs-dev" <core-libs-dev@openjdk.java.net>
> Sent: Monday, May 23, 2022 8:01:44 AM
> Subject: Re: <T> Stream.fromForEach(Consumer<Consumer<T>>)

> 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.

I should have mentioned the Stream.builder, as you said, the Stream.Builder 
stores the whole elements in memory before creating the stream,
it's equivalent to storing the elements in a List and calling List.stream.

Stream.fromForEach like stream.mapMulti() does not stores the elements.
(technically, stream.mapMulti() stores the elements if the default method 
implementation is used but this implementation is only used if you write your 
own Stream, the JDK implementation does not store the elements)

> 
> With best regards,
> Tagir Valeev

regards,
Rémi

> 
> On Sun, May 22, 2022 at 5:54 AM Remi Forax <fo...@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

Reply via email to