【问题标题】:Issue with complex manipulation operation on maps地图上的复杂操作操作问题
【发布时间】:2015-03-02 15:38:25
【问题描述】:

假设我有以下两张地图:

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

我想获得第三张地图,其中包含onetwo的内容。

所以如果一个成员键同时存在于一和二中,那么来自二中条目的列表值将被添加到来自一中条目的列表值中。

使用 java 8 实现这一目标的最佳和最干净的方法是什么?

【问题讨论】:

    标签: java dictionary java-8 java-stream


    【解决方案1】:

    你可以使用合并方法。

    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();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-25
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      • 2016-01-04
      • 2016-11-17
      • 1970-01-01
      相关资源
      最近更新 更多