合并带有重复键的映射列表

4

我有一个列表,包含HashMap<Integer, ArrayList<String>>类型的元素,希望在循环中将它们合并。问题是每个Map的键都从0开始,因此键将重复。使用putAll()方法无法解决这个问题,因为它会覆盖键,最终只返回最后一个Map。

我看到一些通过使用Stream合并两个Map的示例,但在我的情况下,可能会有多个Map。我试图生成一个合并的Map,其中的键是递增的。例如:

假设列表中有2个Map(也可能更多),它们的键都从0开始,但结束值不同。

第一个Map的键从0开始,结束于10

第二个Map的键从0开始,结束于15

是否可以使第二个Map的键从11开始添加? 最终,我需要一个合并的Map,其中第一个键从0开始,最后一个键结束于25。


HashMap不允许重复的键,因此它将覆盖这些键。你在这里想要实现什么样的输出? - Raja Shekar
我猜你的意思是将具有相同键的映射条目的字符串列表合并? - stridecolossus
@RajaShekar编辑了问题以澄清我的需求。键应该是递增的。 - Cugomastik
4个回答

2

我会迭代所有的地图,然后对于你想要合并的每个地图,迭代其条目。对于每个条目,你可以使用computeIfAbsent方法来有条件地为键创建空列表,然后调用值的addAll方法。例如:

List<Map<Integer, List<String>>> maps = List.of(
        Map.of(1, List.of("hello")),
        Map.of(2, List.of("world")),
        Map.of(1, List.of("a"), 2, List.of("b"))
);

Map<Integer, List<String>> combined = new HashMap<>();
for (Map<Integer, List<String>> map : maps) {
    for (Map.Entry<Integer, List<String>> e : map.entrySet()) {
        combined.computeIfAbsent(e.getKey(), k -> new ArrayList<>()).addAll(e.getValue());
    }
}

嗨Mureinik,非常感谢您的回答。不幸的是,地图没有合并,我仍然得到了最后一个地图。 - Cugomastik
1
@Cugomastik 我建议在问题中提供一个 [mre]。上面的代码肯定会将地图合并成一个(在 JShell 中有效)。 - Slaw

2
假设您有一组地图列表,每个地图的键都是在整数范围内的[0-k]、[0-n]、[0,r]...,而您的结果地图应该具有[0-(k+n+r...)]范围内的键设置,下面的内容应该可以工作:
public static void main(String[] args) throws IOException {
   //example list of maps
   List<Map<Integer,List<String>>> mapList = List.of(
           Map.of( 0,List.of("foo","foo"), 
                   1,List.of("bar","bar"), 
                   2,List.of("baz","baz")),
           Map.of( 0,List.of("doo","doo"), 
                   1,List.of("gee","gee"), 
                   2,List.of("woo","woo")),
           Map.of( 0,List.of("cab","cab"), 
                   1,List.of("kii","kii"), 
                   2,List.of("taa","taa"))
   );
   AtomicInteger ai = new AtomicInteger();
   Map<Integer,List<String>> result = 
           mapList.stream()
                   .flatMap(map -> map.values().stream())
                   .collect(Collectors.toMap(list -> ai.getAndIncrement(), Function.identity()));
   result.forEach((k,v) ->{
       System.out.println(k + " : " + v);
   });
}

@Cugomastik 没关系,很高兴能帮到你。 - Eritrean

0

我知道你要求一个地图,但根据你的解释,你的最终解决方案以及现在的键是从0开始的连续整数,你可以只创建一个List<List<String>>。在这种情况下,你可以这样做:

List<List<String>> result = mapList.stream()
               .flatMap(map->map.values().stream())
               .collect(Collectors.toList());                      


0
如果您更喜欢使用流式处理方式
Map<Integer, List<String>> m1;
Map<Integer, List<String>> m2;
Map<Integer, List<String>> m3;

Map<Integer, List<String>> combined = new HashMap<>();
Stream
    .of(m1, m2, m3)
    .flatMap(m -> m.entrySet().stream())
    .forEach(e -> combined.computeIfAbsent(e.getKey(), k -> new ArrayList<>())
            .addAll(e.getValue()));

谢谢您的回答,但如果有50个地图需要合并呢?它可以在循环中使用吗? - Cugomastik
如果有50个,我希望你会有一个列表。然后你可以流式传输该列表。List<Map<Integer, List<String>>> maps。您可以使用maps.stream(),然后跟随其余的代码。 - moh ro
非常感谢您的回答。我已经调整了代码并尝试使用地图列表,但仍然只得到最后一个地图。 - Cugomastik
在上面的例子中,您将找到组合地图中的所有条目。 - moh ro

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