地图上复杂的操作操作问题

Issue with complex manipulation operation on maps

假设我有以下两张地图:

Map<Member, List<Message>> one = ...;//one constructed somehow
Map<Member, List<Message>> two = ...;//two also constructed somehow

我想获取包含onetwo内容的第三张地图。

因此,如果一个成员键同时在一和二中,则二中条目的列表值将添加到一中条目的列表值中。

可能使用 java 8 实现此目的的最佳和最简洁的方法是什么?

您可以使用合并方法。

Map<Member, List<Message>> third = new HashMap<>(one);
two.forEach((k, v) -> third.merge(k, v, (v1, v2) -> {v1.addAll(v2); return v1;}));

这也将修改地图中的列表 one,因为您正在操作相同的参考。如果你不想,即创建一个新列表,你可以这样做:

Map<Member, List<Message>> third = new HashMap<>(one);
two.forEach((k, v) -> third.merge(k, v, (v1, v2) -> Stream.concat(v1.stream(), v2.stream()).collect(toList())));

合并后的列表将是一个新列表,但请注意,对于不在两个映射中的键,情况不会如此。您需要深度复制所有列表才能实现此目的。

刚刚使用 Stream API 添加了另一个解决方案:

Map<Member, List<Message>> third = Stream.of(one, two)
                                         .flatMap(m -> m.entrySet().stream())
                                         .collect(toMap(Map.Entry::getKey, 
                                                        Map.Entry::getValue, 
                                                        (l1, l2) -> Stream.concat(l1.stream(), l2.stream()).collect(toList())));

我也为 proton-pack library 添加了我的贡献。有了这个,你也可以这样实现:

Map<Member, List<Message>> third = MapStream.ofMaps(one, two)
                                            .mergeKeys((l1, l2) -> Stream.concat(l1.stream(), l2.stream()).collect(toList()))
                                            .collect();