说我有以下两个地图:

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


我想获得包含一个和两个内容的第三张地图。

因此,如果成员键同时位于一个和两个中,则来自两个条目的列表值将被添加到来自一个条目的列表值中。

什么是最好的和最干净的方法来实现可能使用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();

08-06 04:16