Hi, 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. Paul. > On 15 Jan 2016, at 16:51, Tagir F. Valeev <amae...@gmail.com> wrote: > > 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. >