Map.Entry methods for streams
paul.sandoz at oracle.com
Fri Jan 15 17:27:01 UTC 2016
We have had multiple attempts at a BiStream for references.
Mike had quite a good one. I thought my last attempt was rather good too :-) it avoided boxing on critical paths, while avoiding much bifurcation of the Spliterator API, and supported some nice use-cases. However, it would likely stick out like a sore thumb when Value types and then Tuples arrive (when? “when they are ready!”), and then we can do much better.
Some small tweaks to Map.Entry might be handy, but i think beyond that and it’s likely to start pulling on a bigger set of use-cases.
> On 15 Jan 2016, at 16:51, Tagir F. Valeev <amaembo at gmail.com> wrote:
> SC> Finally, the Collectors class could do with a new method entriesToMap()
> SC> that collects a stream of Map.Entry back into a Map.
> I was thinking about adding such collector into my library and checked
> StackOverflow to understand the useful scenarios. Seems that having
> entriesToMap() collector without arguments (even along with proposed
> mapValues()/mapKeys()) only would be too limited and solve only some
> subset of interesting problems.
> First, you would need to add versions with
> a) custom merging policy
> b) custom Map factory (probably could be omitted as toMap() does not
> have such overload)
> c) both
> Answers which need this:
> And many more
> Second, to be consistent with the current API you may need to add
> Third, sometimes you need to know both key and value to produce the
> new key. In this case proposed mapValues()/mapKeys() will not work:
> Fourth, very often entries from the stream should be grouped instead,
> so probably something like groupingEntries() should also be added
> (along with Map factory argument, downstream collector argument and
> concurrent version!) The most common scenario is the following:
> mapping(Entry::getValue, toList()))
> And many more
> To my opinion, creating such dedicated collector is even more
> important than toMap() as people understand toMap(Entry::getKey,
> Entry::getValue) much better than cascaded combination of groupingBy,
> mapping and toList. See Stuart Marks explaining:
> Sometimes it works without additional mapping:
> groupingBy(Map.Entry::getKey, summingLong(Map.Entry::getValue))
> Also sometimes you need to swap key and value like here:
> mapping(Map.Entry::getKey, toList()))
> So probably Entry<V, K> swap() method would also be useful!
> In general it's not very evident where to draw the line between API
> simplicity and covered use cases. Hopefully my examples will help to
> take good decision.
> By the way in my library MapStream is called as EntryStream. Like
> IntStream is stream of ints, the EntryStream is stream of entries.
> MapStream would be the stream of maps which is not true. Also in
> context of the Stream API map often means transformation which would
> add the confusion.
> With best regards,
> Tagir Valeev.
More information about the core-libs-dev