Reputation: 47
How can I transform a Map<String, List<String>>
into flattened map based on values grouped as keys.
I.e. from Map<String, List<String>>
to Map<String, String>
(flattened by values)
For an example.
Source map:
<"fuel", ["BMW", "Honda"]>,
<"electric", ["Tesla", "Nio"]>
Flattened map:
[
"BMW" : "fuel",
"Honda" : "fuel",
"Tesla" : "electric",
"Nio" : "electric"
]
Upvotes: 0
Views: 1326
Reputation: 28968
It is not possible to have multiple keys identical according to equals/hashCode
within the same map because it contradicts with idea of the map data structure. Every key must be unique, you can't store multiple entries with the same key in a Map
.
But you can create a list of Map.Entry
objects.
For that, you need to create a stream over the entry set and then flatten each entry by creating a new entry based on car brands (elements of a flatted value) for each key:
Map<String, List<String>> cars =
Map.of("fuel", List.of("BMW", "Honda"),
"electric", List.of("Tesla", "Nio"));
List<Map.Entry<String, String>> entries =
cars.entrySet().stream()
.flatMap(entry -> entry.getValue().stream()
.map(brand -> Map.entry(entry.getKey(), brand)))
.collect(Collectors.toList());
System.out.println(entries);
output
[electric=Tesla, electric=Nio, fuel=BMW, fuel=Honda]
Or maybe your intention was to create a Map<String, String>
that will allow to retrieve car type based on brand (like that: "BMW" : "fuel", "Honda" : "fuel") then it'll make sense.
The overall approach will be similar to the previous one:
flatMap()
by turning an element in the value-list into a new entry;Collectors.toMap()
.But there's a caveat: all values have to be unique or there must be a rule on how to combine/discarde car types.
I'll make an assumption that all brands in the map are unique, otherwise, the code below will fail (to deal with collisions Collectors.toMap()
requires the third argument - mergeFunction
).
Map<String, String> typeByBrand =
cars.entrySet().stream()
.flatMap(entry -> entry.getValue().stream()
.map(brand -> Map.entry(brand, entry.getKey())))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue));
System.out.println(typeByBrand);
output
{Nio=electric, Tesla=electric, BMW=fuel, Honda=fuel}
Upvotes: 3