Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 List<Bar> 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();
fooBarMap.entrySet().stream()
    .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!

like image 695
Alex Pritchard Avatar asked Feb 07 '23 17:02

Alex Pritchard


1 Answers

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.

fooBarMap.entrySet().stream()
    .collect(groupingBy(
        e -> e.getValue().size(),
        mapping(Map.Entry::getKey, toList())
    ));

above assumes static imports of various collectors

like image 129
Misha Avatar answered Apr 20 '23 01:04

Misha