如何将 Stream<Map<String, Map<String, String>>> 合并为单个 Map<String, Map<String, String>>?

Ani*_*rgu 3 java java-stream

我正在尝试将一个Stream<Map<String, Map<String, String>>>对象合并到一个映射中,其中所有Streams.

例如,

final Map<String, someOtherObjectToProcess> someObject;

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

getInfoStream 的签名是

public Stream<Map<String, Map<String, String>>> getInfoStream(Map.Entry<String, someOtherObjectToProcess> entry)
Run Code Online (Sandbox Code Playgroud)

如果我使用,(Collectors.toList())我可以获得这些 Map 对象的列表。

如果我使用上面的代码,示例输出:

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

{
    "name2" : {
        "property":"value"
    }
}]
Run Code Online (Sandbox Code Playgroud)

但我想收集成具有结构的地图

{
    "name" : {
        "property":"value"
    },
    "name2" : {
        "property":"value"
    }
}
Run Code Online (Sandbox Code Playgroud)

前提是密钥是唯一的。

我如何使用 Collectors.toMap() 或任何其他替代方式来做到这一点?

Psh*_*emo 5

当你有

Stream<Map<String, Map<String, String>>> stream = ...
Run Code Online (Sandbox Code Playgroud)

(我假设是的结果.flatMap(this::getInfoStream))你可以打电话

.flatMap(map -> map.entrySet().stream())
Run Code Online (Sandbox Code Playgroud)

从所有映射中创建条目流,这将产生Stream<Map.Entry<String, Map<String, String>>>.

现在,从该流中,您需要做的就是从映射的每个条目中收集键和值。假设每个键在您可以使用的所有地图中都是唯一的

.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Run Code Online (Sandbox Code Playgroud)

但如果键不唯一,您需要决定应在新映射中为同一键放置什么值。我们可以通过填写...部分来做到这一点

.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (vOld, vNew) -> ...));
//                                                                                ^^^
Run Code Online (Sandbox Code Playgroud)

其中vOld保存结果映射中当前在同一键下保存的值,并vNew保存新值(来自当前流“迭代”)。
例如,如果您想忽略新值,您可以简单地返回旧值/当前持有的值(vOld, vNew) -> vOld

简而言之(假设键是唯一的):

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));
Run Code Online (Sandbox Code Playgroud)