How to merge Stream<Map<String, Map<String, String>>> into a single Map<String, Map<String, String>>?

Anirudh Mergu :

I am trying to merge a Stream<Map<String, Map<String, String>>> object into a single map with keys in all the Streams.

For example,

final Map<String, someOtherObjectToProcess> someObject;

final List<Map<String, Map<String, String>>> list = someObject.entrySet()
            .stream()
            .flatMap(this::getInfoStream)
            .collect(Collectors.toList());

The signature for getInfoStream is

public Stream<Map<String, Map<String, String>>> getInfoStream(Map.Entry<String, someOtherObjectToProcess> entry)

if I use (Collectors.toList()) I am able to get a list of these Map objects.

Sample output if I use the above code:

[{
    "name" : {
        "property":"value"
    }
},

{
    "name2" : {
        "property":"value"
    }
}]

But I want to collect into a Map with the structure

{
    "name" : {
        "property":"value"
    },
    "name2" : {
        "property":"value"
    }
}

Provided that the keys will be unique.

How can I do this with Collectors.toMap() or any other alternative way?

Pshemo :

When you have

Stream<Map<String, Map<String, String>>> stream = ...

(which I am assuming is result of .flatMap(this::getInfoStream)) you can call

.flatMap(map -> map.entrySet().stream())

to create stream of entries from all maps which will produce Stream<Map.Entry<String, Map<String, String>>>.

Now from that stream all you need to do is collect key and value from each entry into map. Assuming each key will be unique across all maps you could use

.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

but if keys are not unique you need to decide what value should be placed in new map for same key. We can do it by filling ... part in

.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (vOld, vNew) -> ...));
//                                                                                ^^^

where vOld holds value currently held in result map under same key, and vNew holds new value (from current stream "iteration").
For instance if you want to ignore new value you can simply return old/currently held by (vOld, vNew) -> vOld

So in short (assuming unique keys):

Map<String, Map<String, String>> combinedMap = 
        /*your Stream<Map<String, Map<String, String>>>*/
        .flatMap(map -> map.entrySet().stream())
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=88384&siteId=1