Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reverse a map using streams in java 8 [duplicate]

Tags:

I have a Map<String, Set<String>> that I need to reverse. This would be an example of data:

("AA", ("AA01", "AA02", "AA03")
("BB", ("AA01", "BB01", "BB02")

What I want to obtain is a Map<String, Set<String>> of the reverse relationship, something like this:

("AA01", ("AA", "BB"))
("AA02",("AA"))
("AA03",("AA"))
("BB01",("BB"))
("BB02",("BB"))

I was able to do it, but using foreach:

private Map<String, Set<String>> getInverseRelationship(Map<String, Set<String>> mappings) {
    Map<String, Set<String>> result = new HashMap<>();

    mappings.entrySet().stream().forEach(record -> {
        String key = record.getKey();
        Set<String> itemSet = record.getValue();

        itemSet.forEach(item -> {
            Set<String> values = (result.containsKey(item))? result.remove(item) : new HashSet<>();
            values.add(key);
            result.put(item, values);
        });
    });

    return result;
}

Is there a better way to do it using Java 8 streams API?

like image 251
user1990218 Avatar asked Mar 26 '19 15:03

user1990218


1 Answers

You could use flatMap like :

Map<String, Set<String>> invertedMap = map.entrySet().stream()
        .flatMap(entry -> entry.getValue().stream()
                .map(v -> new AbstractMap.SimpleEntry<>(v, entry.getKey())))
        .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toSet())));

Using SimpleEntry you can store each element from Set as an entry's key and map's key as an entry's value

like image 149
Ruslan Avatar answered Nov 14 '22 23:11

Ruslan