Reputation: 79
I have a map, Map<String, Map<String, String>> myMap = new HashMap<>();
that I would like to remap to get it's values, so that I get as a result Map<String, String>
.
Is it possible to do the mapping using stream API?
I have solved the problem using a for
loop but I'm interested if that could be done using streams.
My solution:
Map<String, String> result = new HashMap<>();
myMap.forEach((k, v) -> {
result.putAll(v);
});
What I want is to get all the values from myMap
and put them in a new Map.
Upvotes: 2
Views: 1641
Reputation: 28968
You need to flatten the entries of the nested maps which can be done using either flatMap()
or mapMulty()
.
And then apply collect()
with the minimalistic two-args flavor of Collector toMap()
passed as an argument. It would be sufficient since you don't expect duplicates.
Here's an example using flatMap()
:
Map<String, Map<String, String>> myMap = new HashMap<>();
Map<String, String> res = myMap.entrySet().stream() // stream of maps
.flatMap(entry -> entry.getValue().entrySet().stream()) // stream of map entries
.collect(Collectors.toMap(
Map.Entry::getKey, // key mapper
Map.Entry::getValue // value mapper
));
Example with Java 16 mapMulti()
used for flattening the data:
Map<String, Map<String, String>> myMap = new HashMap<>();
Map<String, String> res = myMap.entrySet().stream() // stream of maps
.<Map.Entry<String, String>>mapMulti((entry, consumer) ->
entry.getValue().entrySet().forEach(consumer) // stream of map entries
)
.collect(Collectors.toMap(
Map.Entry::getKey, // key mapper
Map.Entry::getValue // value mapper
));
Upvotes: 1
Reputation: 6985
If you are certain there are no duplicate keys, you can do it like this.
Map<String, String> res = myMap.values()
.stream()
.flatMap(value -> value.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue);
If there may be duplicate keys between the inner maps, you will have to introduce merge function to resolve conflicts. Simple resolution keeping the value of the second encountered entry may look like this:
Map<String, String> res = myMap.values()
.stream()
.flatMap(value -> value.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v2));
Basically, stream the values, which are Map
s, flatten them to a stream of entries and collect the entries in a new Map.
Upvotes: 1