1

I am trying to use map to map a set of keys into a Map of String to Set of Integer. Ideally I want to get all the value sets and collect them into a single set.

Lets say I have:

Map<String, List<Integer>> keyValueMap = new HashMap<>();
Set<String> keys = new HashSet<>();
Set<String> result = new HashSet<>();

I have tried:

result.addAll(keys.stream().map(key -> keyValueMap.get(key)).collect(Collectors.toSet());

This nets me an error saying addAll() is not applicable for the type Set>. I have tried replacing map() with flatMap() but I can't seem to get the syntax right if that is the solution.

What is the correct syntax to make this work?

Thanks!

1 Answer 1

2

It looks like the type of result should be Set<Integer> instead of Set<String>.


With your snippet, you're attempting to invoke Set#addAll on a Set<Integer>, but the argument being passed is a Set<List<Integer>>, which doesn't compile.

To ameliorate your issue, one solution is to use flatMap instead of map:

result.addAll(keys.stream()
                  .flatMap(key -> keyValueMap.get(key).stream())
                  .collect(Collectors.toSet()));

A logically equivalent snippet is:

result.addAll(keys.stream()
                  .map(keyValueMap::get)
                  .flatMap(List::stream)
                  .collect(Collectors.toSet()));

Another solution would be to utilize Map#values:

result.addAll(keyValueMap.values().stream()
                         .flatMap(List::stream)
                         .collect(Collectors.toSet()));
Sign up to request clarification or add additional context in comments.

12 Comments

@TimB. Ameliorate, meaning to make something better. In this case, it refers to fixing your compiler error. And if I were you, I'd take advantage of Map#keySet and Map#values.
@TimB. Take a look at the documentation for Map. It has many methods that could potentially suit your use-case.
My use case was actually a lot more complicated than my question above, so I am not quite sure there is better way to take advantage of Map#keySet and Map#values, but I will take another read through the docs and see.
Perfect, thank you! The second solution was not compilable for me for some reason so I am just sticking with the first.
There is no need for the addAll. Just assign the result of the collect operation to result, e.g. Set<Integer> result = keys.stream() .flatMap(key -> getOrDefault(key, Collections.emptyList()).stream()) .collect(Collectors.toSet());
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.