Map.Entry methods for streams
Tagir F. Valeev
amaembo at gmail.com
Fri Jan 15 15:51:02 UTC 2016
Hello!
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:
http://stackoverflow.com/a/22132422/
http://stackoverflow.com/a/33724926/
http://stackoverflow.com/a/30084289/
And many more
Second, to be consistent with the current API you may need to add
entriesToConcurrentMap()
Third, sometimes you need to know both key and value to produce the
new key. In this case proposed mapValues()/mapKeys() will not work:
http://stackoverflow.com/a/34766036/
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:
groupingBy(Entry::getKey,
mapping(Entry::getValue, toList()))
http://stackoverflow.com/a/25246138/
http://stackoverflow.com/a/31488612/
http://stackoverflow.com/a/30877403/
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:
http://stackoverflow.com/a/28599035/
Sometimes it works without additional mapping:
groupingBy(Map.Entry::getKey, summingLong(Map.Entry::getValue))
http://stackoverflow.com/a/34325686/
http://stackoverflow.com/a/31751786/
Also sometimes you need to swap key and value like here:
groupingBy(e->e.getValue().get(0),
mapping(Map.Entry::getKey, toList()))
http://stackoverflow.com/a/30652372/
http://stackoverflow.com/a/33900949/
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
mailing list