EnumeratedStream

ІП-24 Олександр Ротань rotan.olexandr at gmail.com
Sun Apr 21 10:49:16 UTC 2024


I have heard your proposal. Your approach indeed for sure has its
advantages.

One thing I don't like referring to is Valhalla. It's not even a
preview and no one really knows when it will be, relying on it when
designing API now would be strange to say the least.

One possible thing that could dramatically simplify implementation of my
approach is introduction of generic reification, which would allow
primitives as type params. I am currently studying the working of javac and
possible implementation of this is one of the topics in my research.
However, let's stick to what we have in jdk right now from now on.

I would like to hear opinions of other people regarding the design of such
API, especially David and Remi, since, as I understand, that's not the
first time they witness a discussion like this, so maybe they have
something to tell here.

вс, 21 апр. 2024 г. в 06:35, - <liangchenblue at gmail.com>:

> On Sat, Apr 20, 2024 at 8:29 PM ІП-24 Олександр Ротань <
> rotan.olexandr at gmail.com> wrote:
>
>> Gatherers could be effectively terminal, but I don't think Gatherer API
>> designers intended it to be. In related JEP, gatherers are described as a
>> way to declare custom intermediate operations, and introducing "terminal"
>> gatherers would be misleading.
>>
> I will show you an API that expands on collectors too.
>
>>
>> Talking about performance, not even considering gather() method itself,
>> creating an instance of Indexed object for each value in stream is costy
>> and might turn into a nightmare for infinite streams.
>>
> We will have value objects soon (Project Valhalla), by then the object
> creation will be much more lightweight as it's effectively a tuple. This is
> not really a thing of concern.
>
>>
>> As for internals of Stream API right now, I am not aware about its
>> current state, so not much to say here except that adding a new type of
>> streams that just slightly extends existing functionality might not be that
>> harmful, I guess.
>>
>> Regarding API exposure, I don't think that moving it from stream directly
>> to Gatherers factory would be much of a deal since to see index-aware
>> methods user must explicitly convert stream to enumerated.
>>
> Having another set of EnumeratedStream APIs and implementations is going
> to be a nightmare to maintain. Also it has bad interpolatability to convert
> itself back into regular streams for other usages, while Stream<Indexed<T>>
> are much better in that aspect.
>
>>
>> I also think the I didn't express my point about index consistency clear
>> enough. Consider following:
>>
> Notice that Stream.filter retains instead of drops the matching elements!
> Since otherwise your results don't make sense. I will assume you mean
> "filter" like "dropIf"
>
>>
>> List.of(1,2,3).stream().enumerated().filter((idx, i) -> i*idx <
>> 2).map((idx, val) -> idx * val)
>>
>> Result : (4, 9)
>>
> Does idx start from 0 or 1? All Java indices start from 0, having it start
> from 1 in enumerated is really weird. I will assume you mean [2, 6]=[1*2,
> 2*3]
> Your use case is even simpler, this case can be covered in a simple
> gatherer like this:
> Gatherer.ofSequential(() -> new int[] {0},
>             Gatherer.Integrator.ofGreedy((counter, v, sink) ->
>                     sink.push(new Indexed<>(counter[0]++, v))))
> Better than writing thousands lines of new code. The functionalities are
> already implemented in my sample project in
>
> https://github.com/liachmodded/IndexedStream/tree/main/src/main/java/com/github/liachmodded/indexedstream
>
>>
>> With your approach
>>
>> List.of(1,2,3).stream().gather(Gatherers.filterIndexed((idx, val) ->
>> idx*val < 2)).gather(Gatherers.mapIndexed((idx, val) -> idx * val))
>>
>> Result : (2, 6)
>>
> I will assume you mean [0, 3]=[0*2, 1*3]
>
>>
>> Not only second option is much more verbose, but also indexes of stream
>> are inconsistent between operations.
>>
> Then what does EnumeratedStream serve? We would assume the enumeration
> means the enumeration at the current stage so we want the number
> immediately. If you want the enumeration at a particular stage, it's better
> to zip your stream items with an index like my gatherer above at an
> explicit step.
>
> Also I have already made a showcase git repository with your two test
> cases at
>
> https://github.com/liachmodded/IndexedStream/blob/main/src/test/java/com/github/liachmodded/indexedstream/IndexedGatherersTest.java
> Feel free to rant and tell what you really want that aren't served by
> these few simple classes.
>
>>
>> PS: regarding findIndex, I did some benchmarking today, you might like to
>> take a look. On average list-based version outperform collector and
>> gatherer-based in more then 10 times. And also lists in stdlib doesn't have
>> any hashcode-based implementations. I wrote 19 implementations in list
>> subclasses and none of them had anything but simple traversing logic inside
>> indexOf. But that's topic of another thread
>>
> Thanks for the prompt, I will look at it and reply in the other thread.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20240421/16c66919/attachment-0001.htm>


More information about the core-libs-dev mailing list