Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flip key, value in a HashMap using Java8 Stream

I have a Map in following structure and I want to flip the key and value.

Map<String, List<String>> dataMap

Sample data :

acct01: [aa, ab, ad],
acct02: [ac, ad]
acct03: [ax, ab]

Want this data to be converted to,

aa: [acct01],
ab: [acct01, acct03],
ac: [acct02],
ad: [acct01, acct02],
ax: [acct03]

Want to know if there is a java 8 - stream way to transform the Map.

My Current implementation in (without Stream)

Map<String, List<String>> originalData = new HashMap<String, List<String>>();
        originalData.put("Acct01", Arrays.asList("aa", "ab", "ad"));
        originalData.put("Acct02", Arrays.asList("ac", "ad"));
        originalData.put("Acct03", Arrays.asList("ax", "ab"));

        System.out.println(originalData);
        Map<String, List<String>> newData = new HashMap<String, List<String>>();
        originalData.entrySet().forEach(entry -> {
            entry.getValue().forEach(v -> {
                if(newData.get(v) == null) {
                    List<String> t = new ArrayList<String>();
                    t.add(entry.getKey());
                    newData.put(v, t);
                } else {
                    newData.get(v).add(entry.getKey());
                }
            });
        });
        System.out.println(newData);

input and output, {Acct01=[aa, ab, ad], Acct02=[ac, ad], Acct03=[ax, ab]} {aa=[Acct01], ab=[Acct01, Acct03], ac=[Acct02], ad=[Acct01, Acct02], ax=[Acct03]}

Looking for way to implement using Stream.

like image 812
Bala Avatar asked Dec 05 '25 09:12

Bala


2 Answers

Get the stream for the entry set, flatten it out into one entry per key-value pair, group by value, collect associated keys into a list.

import static java.util.Arrays.asList;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;

import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

<K, V> Map<V, List<K>> invert(Map<K, List<V>> map) {
    return map.entrySet().stream().flatMap(
        entry -> entry.getValue().stream().map(
            value -> new SimpleImmutableEntry<>(
                entry.getKey(),
                value
            )
        )
    ).collect(
        groupingBy(
            Entry::getValue,
            mapping(
                Entry::getKey,
                toList()
            )
        )
    );
}
like image 146
gdejohn Avatar answered Dec 08 '25 17:12

gdejohn


Here is the solution by Java 8 stream library: StreamEx

newData = EntryStream.of(originalData).invert().flatMapKeys(k -> k.stream()).grouping();
like image 22
123-xyz Avatar answered Dec 08 '25 17:12

123-xyz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!