Adapting an already existing stream API to a Stream

Remi Forax forax at univ-mlv.fr
Fri Jan 11 13:55:53 PST 2013


On 01/11/2013 09:54 PM, Brian Goetz wrote:
> There are a few ways to build a Stream, in order of increasing work 
> (and increasing stream quality):
>
>  - Iterator
>  - Iterator + size
>  - Spliterator
>  - Spliterator with exactSize / exactSplits
>
> With a raw Iterator, we won't know the size of the stream, nor will we 
> get very good splits.  Adding the size addresses the first problem.
>
> Going to a Spliterator addresses the "not good splits" problem 
> (assuming your spliterator is decent.)
>
> Adding in exactSize/exactSplits enables optimizations that avoid 
> copies when merging parallel results.
>
> Converting any push-oriented source to a Stream requires writing an 
> Iterator/Spliterator.  Which may in turn require you to do some 
> buffering on your own.  (We do something similar internally, when we 
> want to iterate nontrivial streams one element at a time; we pull 
> elements from the upstream source, create a chain of sinks, and the 
> last sink is a buffer, and then the iterator reads from the buffer, 
> and when the buffer is empty, we push more elements into the sink 
> chain from upstream.)

The whole pipeline works in a push way but the interface used to push 
the element into the pipeline uses the pull way.
You can't do any buffering because you may have to buffer all the 
elements unlike with mapMulti by example.

Basically, I think Spliterator should not be based on Iterator but on a 
push based API because you can extract elements from an iterator and 
push them in the pipeline and not do the other way around.

interface Pusher<E> {
   // returns false if the pusher doesn't accept any other value
   boolean accept(E element);
}

interface SplitPusher<E> {
   Pusher<E> pusher();
   SplitPusher<E> trySplit();
   long exactSizeIfKnown();
   boolean hasExactSplits();
}

Rémi

>
> On 1/11/2013 3:36 PM, Remi Forax wrote:
>> On 01/11/2013 09:11 PM, Brian Goetz wrote:
>>> Blocks don't return anything.  Where do the elements go?
>>
>> You pass a Block as parameter, so it depends on the block.
>> By example,
>>
>> static void generateAll(Block<? super Integer> block) {
>>    for(int i=0; i<1_000; i++) {
>>      block.accept(i);
>>    }
>> }
>>
>> or with a cancel
>>
>> interface Pusher<T>{   // the dual of Iterator
>>    boolean isStopped();
>>    void accept(T element);
>> }
>>
>> static void generateAll(Pushiterator<? super Integer> pusher) {
>>    for(int i=0; i<1_000 && !pusher.isStopped(); i++) {
>>      pusher.accept(i);
>>    }
>> }
>>
>> Rémi
>>
>>>
>>> On 1/11/2013 3:00 PM, Remi Forax wrote:
>>>> Let say I have an API with one static method generateAll that takes a
>>>> Block as parameter and generate all elements by calling the Block n
>>>> times.
>>>> How can I create a Stream on top of this API ?
>>>>
>>>> Rémi
>>>>
>>



More information about the lambda-libs-spec-experts mailing list