Hello everyone! Thanks for your responses

I will start of by answering to Viktor

I guess a "simple" implementation of an N-ary concat could work, but it
> would have performance implications (think a recursive use of
> Stream.concat())


I too find just the addition of small reduction-performing sugar methods
rather unsatisfactory and most certainly not bringing enough value to be
considered a valuable addition. Moreover, I have not checked it myself, but
I would dare to guess that popular utility libraries such as Guava or
Apache Commons already provide this sort of functionality in their utility
classes. Though, if this method could bring some significant performance
benefits, I think it may be a valuable candidate to consider. Though, to me
as a user, the main value would be uniformity of the API and ease of use
and read. The main reason I am writing about this in the first place is the
unintuitive inconsistency with many other static methods-creators that
happily accept varargs

I may play around with this spliterator code you have linked to to see if I
could make it generalized for arrays of streams

Now, answering to Pavel

Is it such a useful use case, though? I mean, it's no different from
> SequenceInputStream(...) or Math.min/max for that matter. I very rarely
> have to do Math.min(a, Math(min(b, c)) or some such.


I certainly see your point, but I would dare to say that most applications
rely on the streams much more than SequenceInputStream and Math classes,
and their lookalikes. Stream.concat is primarily a way to merge a few
datasource outputs into one, for later uniform processing, which, in the
nutshell, is one of the most common tasks in data-centric applications. Of
course, not every such use case has characteristics that incline developers
to use Stream.concat, such as combination of Stream.of and
Collection.stream() sources, and even if they do, not every case that fits
previous requirement requires to merge more than 2 sources. However, for
mid-to-large scale apps, for which java is known the most, I would say it's
fairly common. I went over our codebase and found that there were at least
10+ usages of concat, and a few of them followed this kinda ugly pattern of
nested concates.

Separately, it's not just one method. Consider that `concat` is also
> implemented in specialized streams such as IntStream, DoubleStream, and
> LongStream.


This is unfortunate, but I would dare to say that once Reference
spliterrator is implemented, others may also be derived by analogy fairly
quickly

And last but not least, answering Daniel

Not immediately obvious but you can create a Stream<Stream<T>> using
> Stream.of and reduce that using Stream::concat to obtain a Stream<T>.

Something along those lines:

```
> var stream = Stream.of(Stream.of(1,2,3), Stream.of(4), Stream.of(5, 6,
> 7, 8)).reduce(Stream.empty(), Stream::concat, Stream::concat);


This is what I meant by "reduction-like" implementation, which is fairly
straightforward, but just from the looks of it, one could assume that this
solution will surely have performance consequences, even if using  flatmap
insead of reduce. Not sure though, how often people would want to use such
approach on the array of streams huge enough for the performance difference
to be noticable, though I would assume that there is a non-linear scale of
consumed time and resources from the length of streams array due to the
implementation of concat method.

Nevertheless, this is an acceptable workaround for such cases, even though
not the most readable one. Even if this approach is accepted as sufficient
for such cases of n-sized array of streams merging, It would probably make
some sense to put note about it in the docs of the concat method. Though,
not having concat(Stream..) overload would still remain unintuitive for
many developers, including me

Thanks everybody for the answers again

Best regards

On Wed, Sep 17, 2025 at 5:15 PM Pavel Rappo <pavel.ra...@gmail.com> wrote:

> >  this would be a great quality of life improvement
>
> Is it such a useful use case, though? I mean, it's no different from
> SequenceInputStream(...) or Math.min/max for that matter. I very
> rarely have to do Math.min(a, Math(min(b, c)) or some such. And those
> methods predate streams API by more than a decade.
>
> Separately, it's not just one method. Consider that `concat` is also
> implemented in specialized streams such as IntStream, DoubleStream,
> and LongStream.
>
> On Wed, Sep 17, 2025 at 2:58 PM Olexandr Rotan
> <rotanolexandr...@gmail.com> wrote:
> >
> > Greetings to everyone on the list.
> >
> > When working on some routine tasks recently, I have encountered a,
> seemingly to me, strange decision in design of Stream.concat method,
> specifically the fact that it accepts exactly two streams. My concrete
> example was something along the lines of
> >
> > var studentIds = ...;
> > var teacherIds = ...;
> > var partnerIds = ...;
> >
> > return Stream.concat(
> >     studentIds.stream(),
> >     teacherIds.stream(),
> >     partnerIds.stream() // oops, this one doesn't work
> > )
> >
> > so I had to transform concat to a rather ugly
> > Stream.concat(
> >     studentIds.stream(),
> >     Stream.concat(
> >         teacherIds.stream(),
> >         partnerIds.stream()
> >     )
> > )
> >
> > Later on I had to add 4th stream of a single element (Stream.of), and
> this one became even more ugly
> >
> > When I first wrote third argument to concat and saw that IDE highlights
> it as error, I was very surprised. This design seems inconsistent not only
> with the whole java stdlib, but even with Stream.of static method of the
> same class. Is there any particular reason why concat takes exactly to
> arguments?
> >
> > I would say that, even if just in a form of sugar method that just does
> reduce on array (varagrs) of streams, this would be a great quality of life
> improvement, but I'm sure there also may be some room for performance
> improvement.
> >
> > Of course, there are workarounds like Stream.of + flatmap, but:
> >
> > 1. It gets messy when trying to concat streams of literal elements set
> (Stream.of) and streams of collections or arrays
> > 2. It certainly has significant performance overhead
> > 3. It still doesn't explain absence of varagrs overload of concat
> >
> > So, once again, is there any particular reason to restrict arguments
> list to exactly two streams? If not, I would be happy to contribute
> Stream.concat(Stream... streams) overload.
> >
> > Best regards
> >
> >
> >
>

Reply via email to