Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java8: How to Convert Map<X, List<Y>> to Map<Y,X> using Stream?

I am new to Java8. A problem that I want to solve is to convert Map> to Map using Stream. For example:

input: {A => [B, C, D], E => [F]}
output: {B => A, C => A, D => A, F => E}

Let's assume that there is no duplicated value in List. How to do it in java 8 stream in an elegant way?

Cheers, Wei

like image 440
liuwei7923 Avatar asked Dec 24 '22 01:12

liuwei7923


2 Answers

If you want a solution without forEach() you can do:

    Map<Integer, String> pam = 
            map.entrySet().stream()
            .flatMap(x -> x.getValue().stream().map(v -> new AbstractMap.SimpleEntry<>(v, x.getKey())))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

For each Entry like "3"-> [3,4,5,6] a Stream of Entries like 3->3,4->3,5->3,6->3 is created, using flatMap it can be flattened to one stream, then Collectors.toMap() creates the final Map.

like image 168
user140547 Avatar answered Dec 28 '22 07:12

user140547


Assuming

    Map<String, List<Integer>> map = new HashMap<>();
    Map<Integer,String>        pam = new HashMap<>();

This will do what you want

    map.entrySet().stream().forEach(e -> e.getValue().stream().forEach(v -> pam.put(v, e.getKey())));

This takes advantage of the fact that Set<E> implements stream() from Collection. The rest is just plugging things into the right place.

Or, as suggested by @user140547 (thank you), an even simpler solution

    map.forEach((k,v) -> v.forEach(vv -> pam.put(vv, k)));
like image 24
Jim Garrison Avatar answered Dec 28 '22 07:12

Jim Garrison