Convert Map<String, Object> to Map<String, Set<Object>> with filter and streams

  • A+

I would like to convert my map which looks like this:

{   key="someKey1", value=Apple(id="1", color="green"),   key="someKey2", value=Apple(id="2", color="red"),   key="someKey3", value=Apple(id="3", color="green"),   key="someKey4", value=Apple(id="4", color="red"), } 

to another map which puts all apples of the same color into the same list:

{   key="red", value=list={apple1, apple3},   key="green", value=list={apple2, apple4},   } 

I tried the following:

Map<String, Set<Apple>> sortedApples = appleMap.entrySet()     .stream()     .collect(Collectors.toMap(l -> l.getColour, ???)); 

Am I on the right track? Should I use filters for this task? Is there an easier way?


if you want to proceed with toMap you can get the result as follows:

map.values()  // get the apples    .stream() // Stream<Apple>    .collect(toMap(Apple::getColour, // group by colour              v ->  new HashSet<>(singleton(v)), // have values as set of apples           (l, r) -> {l.addAll(r); return l;})); // merge colliding apples by colour 

but this is better with groupingBy and toSet as downstream:

map.values().stream().collect(groupingBy(Apple::getColour, toSet())); 

You could also do it without a stream:

Map<String, Set<Apple>> res = new HashMap<>(); map.values().forEach(a -> res.computeIfAbsent(a.getColour(), e -> new HashSet<>()).add(a)); 


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: