Alex Pritchard Alex Pritchard - 1 year ago 35
Java Question

Use streams to group Map<Foo,List<Bar>> based on size of the List<Bar>

I'm trying to transform data of this format:

Map<Foo, List<Bar>> mapFooToBars; //start Map
Map<Integer, List<Foo>> mapListSizeToFoos //destination Map

I'd like to create a grouping based on the size of the
for each entry, so that in my output map, I would have a list of all Foos that have 0 Bars together, all Foos that have 1 Bar together, and so on.

I was trying to do this:

Map<Foo, List<Bar>> fooBarMap = whatever();
.collect(Collectors.groupingBy(entry -> entry.getValue().size()));
//expected Map<Integer,Entry<Foo, List<Bar>> which
//could be transformed into Map<Integer,Foo> pretty easily

I apparently am unclear on how groupingBy works exactly, as this is giving me a "getValue() is undefined for the type Object" error. Somewhere along the line I'm losing the type information about entrySet I guess? It made me wonder if this was not the best way to go about this. Any help appreciated!


You are on the right track. You should use groupingBy but with mapping(Map.Entry::getKey, toList()) as the second parameter. This will collect the keys into a list and those lists will be the values of the resulting map.

        e -> e.getValue().size(),
        mapping(Map.Entry::getKey, toList())

above assumes static imports of various collectors