使用flatMap将Map列表转换为Map

8

我该如何使用flatMapList<Map<String,String>> 合并为 Map<String,String>

我已经尝试了以下方法:

final Map<String, String> result = response
    .stream()
    .collect(Collectors.toMap(
        s -> (String) s.get("key"),
        s -> (String) s.get("value")));
result
    .entrySet()
    .forEach(e -> System.out.println(e.getKey() + " -> " + e.getValue()));

这个不起作用。


2
键可以发生碰撞吗,还是它们保证唯一?如果它们可以碰撞,你想要采取什么行动——取第一个,将它们连接在一起,保持计数,还是其他的? - ErikE
你想做什么?将所有键连接在一起,值也是如此吗? - Paul Lemarchand
3个回答

16
假设您的列表中包含的地图中没有冲突的键,请尝试以下操作:
Map<String, String> maps = list.stream()
    .flatMap(map -> map.entrySet().stream())
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

你会在我的回答中看到:将合并函数添加到“toMap”调用中可以避免冲突问题。 - sprinter
1
@sprinter,您所说的“merge”功能是指Set::stream吗?这不是必要的。如果您在一个映射中添加重复的键,则最后一个键将覆盖前面的键。 - VHS
不,toMap 不是这样用的。从文档中可以得知:"如果映射键包含重复项(根据 Object.equals(Object)),则在执行集合操作时将引发 IllegalStateException 异常。如果映射键可能有重复项,请改用 toMap(Function, Function, BinaryOperator)。" 我在解决方案中使用的二元运算符是 Map::putAll,它可以处理重复项。 - sprinter

6

一个非常简单的方法是只使用putAll

Map<String, String> result = new HashMap<>();
response.forEach(result::putAll);

如果你特别想在单一流操作中实现这个功能,那么可以使用归约:

response.stream().reduce(HashMap<String, String>::new, Map::putAll);

或者,如果您真的想使用flatMap

response.stream().map(Map::entrySet).flatMap(Set::stream)
    .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, Map::putAll));

请注意在最终备选方案中的合并功能。

4

如果您不介意覆盖键,可以使用collectMap合并为单个映射,甚至无需使用flatMap

public static void main(String[] args) throws Exception {
    final List<Map<String, String>> cavia = new ArrayList<Map<String, String>>() {{
        add(new HashMap<String, String>() {{
            put("key1", "value1");
            put("key2", "value2");
            put("key3", "value3");
            put("key4", "value4");
        }});
        add(new HashMap<String, String>() {{
            put("key5", "value5");
            put("key6", "value6");
            put("key7", "value7");
            put("key8", "value8");
        }});
        add(new HashMap<String, String>() {{
            put("key1", "value1!");
            put("key5", "value5!");
        }});
    }};

    cavia
            .stream()
            .collect(HashMap::new, HashMap::putAll, HashMap::putAll)
            .entrySet()
            .forEach(System.out::println);
}

将输出:

key1=value1!
key2=value2
key5=value5!
key6=value6
key3=value3
key4=value4
key7=value7
key8=value8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接