0

For example I have a Map<String, List>:

{
    "North America": ["New York", "Vancouver"], 
    "Europe": ["London", "Paris"]
}

and I want to convert it to a Map<String, String>

{
    "New York": "North America",
    "Vancouver": "North America",
    "London": "Europe", 
    "Paris": "Europe"
}

How can I accomplish this using stream() in Java 8?

  • 3
    Please show us what you have tried so far and which part you are stuck on. If you are completely new to streams then a [tutorial](https://mydeveloperplanet.com/2020/09/23/java-streams-by-example/) may help – sorifiend Mar 11 '21 at 02:28
  • Need to be careful to transform to something that maybe can have duplicate keys ... using your analogy you might have to put this into the map "Melbourne" : "Australia", "Melbourne" : "England", "Melbourne" : "North America" [3 of these IOWA, Arkansas, and Florida]. – Mr R Mar 11 '21 at 02:50
  • 1
    I don't believe you'll find an elegant solution using `stream()` alone as you need to account for the duplicate keys/values. Iterating the maps may be the best option, though I could be wrong. – Zephyr Mar 11 '21 at 02:55
  • @Zephyr There's `Collectors.groupingBy` that will handle the duplicates automatically. – Benjamin M Mar 11 '21 at 03:04

1 Answers1

1

You can do it like this.

The data

Map<String, List<String>> map = Map.of("North America",
        List.of("New York", "Vancouver", "Paris"), "Europe",
        List.of("London", "Paris"));

The process

  • stream the entrySet
  • flatMap the list and map to an array
  • then build the new map with the results of the array.
  • I added a merge function to handle duplicate keys in case a city is in two countries.

Map<String, String> result = map.entrySet().stream()
        .flatMap(e -> e.getValue().stream()
                .map(str -> new String[] { str, e.getKey() }))
        .collect(Collectors.toMap(a -> a[0], a -> a[1],
                (countries, country)->countries + ", " + country,
                HashMap::new));

result.entrySet().forEach(System.out::println);

prints

New York=North America
Vancouver=North America
London=Europe
Paris=Europe, North America

Instead of using string concatenation to handle duplicates you could also do this using a Map<String,List<String>> to handle duplicate cities. Here is how that would look.

Map<String, List<String>> result = map.entrySet().stream()
        .flatMap(e -> e.getValue().stream()
                .map(str -> new String[] { str, e.getKey() }))
        .collect(Collectors.groupingBy(a -> a[0],
            Collectors.mapping(a -> a[1], Collectors.toList())));
WJS
  • 36,363
  • 4
  • 24
  • 39