0

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" ] 
2
  • Now imagine you have your Map<String, String>. What should be result of yourMap.get("fuel")? Should it be "BMW" "Honda" OR maybe both grouped, like ["BMW", "Honda"] (like you had originally...)? Commented Feb 27, 2022 at 0:38
  • I should have rephrased my question in a better way. My intention was to create a name value pair out of the map which contains value as a list of string Commented Feb 27, 2022 at 4:34

1 Answer 1

4

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:

  • create a stream over the entry set;
  • flatten each entry using flatMap() by turning an element in the value-list into a new entry;
  • collect elements to a map with 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} 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.