Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flatten the map and associate values using Java 8 Stream APIs

Suppose that I have a map of a set of strings to an integer value:
Map<HashSet<String>, Integer> map = new HashMap<>().

For example, the map is (we assume no duplicate strings):

{x,y}   ->  2
{z}     ->  3
{u,v,w} ->  4

How can I get another_map of type Map<String, Integer> as follows, using Java 8 Stream APIs:

x -> 2
y -> 2
z -> 3
u -> 4
v -> 4
w -> 4

It looks like a flatMap operation, but how could I associate the Integer values with each String key appropriately?

like image 347
hengxin Avatar asked Mar 14 '23 03:03

hengxin


1 Answers

You can do this creating intermediate Map.Entry objects like this:

Map<String, Integer> result = map.entrySet().stream()
   .<Entry<String, Integer>>flatMap(entry -> 
       entry.getKey()
            .stream()
            .map(s -> new AbstractMap.SimpleImmutableEntry<>(s, entry.getValue())))
   .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

Alternatively you may use any other pair/tuple type you have in your project.

Note that my free StreamEx library supports handling such cases in more clean way (internally it's the same as above):

Map<String, Integer> result = EntryStream.of(map).flatMapKeys(Set::stream).toMap();

The EntryStream class extends Stream<Map.Entry> and provides additional helpful methods like flatMapKeys or toMap.

like image 187
Tagir Valeev Avatar answered Apr 07 '23 06:04

Tagir Valeev