Paul Sandoz paul.sandoz at
Fri Jun 15 23:36:29 UTC 2018

Hi Tagir,

This is looking good.

My current favorite name for the factory method is “bisecting” since we are dividing the collector into two collectors, the results of which are then merged.
Suggested first paragraph of the factory method:

  "Returns a collector that passes the input elements to two specified collectors and merges their results with the specified merge function.”


> On Jun 15, 2018, at 4:26 AM, Tagir Valeev <amaembo at> wrote:
> Hello!
> I created a preliminary webrev of my own implementation (no testcases yet):
> If anybody wants to sponsor my implementation, I will happily log an issue and write tests.
> The name "pairing" was invented by me, but as I'm not a native English speaker I cannot judge whether it's optimal, so better ideas are welcome.
> Also I decided to remove accumulator types from public type variables. They do not add anything to type signature, only clutter it 
> increasing the number of type parameters from 4 to 6. I think it was a mistake to expose the accumulator type parameter in other cascading collectors 
> like filtering(), collectingAndThen(), groupingBy(), etc. I'm not insisting though, if you feel that conformance to existing collectors is 
> more important than simplicity.
> With best regards,
> Tagir Valeev.
> On Fri, Jun 15, 2018 at 5:05 AM Brian Goetz <brian.goetz at> wrote:
> > Well, I don't see the need to pack the two results into a Map.Entry 
> > (or any similar) container as a drawback. 
>  From an "integrity of the JDK APIs" perspective, it is unquestionably a 
> drawback.  These items are not a Key and an associated Value in a Map; 
> it's merely pretending that Map.Entry really means "Pair".  There's a 
> reason we don't have a Pair class in the JDK (and no, let's not reopen 
> that now); using something else as a Pair proxy that is supposed to have 
> specific semantics is worse. (It's fine to do this in your own code, but 
> not in the JDK. Different standards for code that has different audiences.)
> Tagir's proposed sidestepping is nice, and it will also play nicely with 
> records, because then you can say:
>       record NameAndCount(String name, int count);
>       stream.collect(pairing(collectName, collectCount, NameAndCount::new));
> and get a more properly abstract result out.  And its more in the spirit 
> of existing Collectors.  If you want to use Map.Entry as an 
> _implementation detail_, that's fine.
> I can support this form.
> > I also don't see a larger abstraction like BiStream as a natural fit 
> > for a similar thing. 
> I think the BiStream connection is mostly tangential.  We tried hard to 
> support streams of (K,V) pairs when we did streams, as Paul can attest, 
> but it was a huge complexity-inflater and dropping this out paid an 
> enormous simplification payoff.
> With records, having streams of tuples will be simpler to represent, but 
> no more performant; it will take until we get to value types and 
> specialized generics to get the performance we want out of this.

More information about the core-libs-dev mailing list