【问题标题】:Merge two maps in specific order按特定顺序合并两个地图
【发布时间】:2020-10-28 10:37:39
【问题描述】:

我有两个地图 map1 和 map2。我想按特定顺序组合这两个地图。 假设我有两张地图

Map<String, String> map1 = new HashMap<>();
Map<String, String> map2 = new HashMap<>();

map1.put("id1", "3895");
map1.put("id2", "6754");
map1.put("id3", "7896");
map1.put("id4", "1122");

map2.put("month1", "Jan");
map2.put("month2", "Mar");
map2.put("month3", "Dec");
map2.put("month4", "Aug");

现在我想组合这两张地图,以便第三张地图的元素按以下顺序排列。 Map3 中的预期顺序。

("id1", "3895")
("month1", "Jan")
("id2", "6754")
("month2", "Mar")
("id3", "7896")
("month3", "Dec")
("id4", "1122")
("month4", "Aug")

我如何实现这一目标?我尝试使用 putAll 和 LinkedHashMap,但结果不是预期的。

使用 LinkedHashMap -

Map<String, String> merged = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (x, y) -> y, LinkedHashMap::new));

结果是

("id1", "3895")
("id2", "6754")
("id3", "7896")
("id4", "1122")
("month1", "Jan")
("month2", "Mar")
("month3", "Dec")
("month4", "Aug")

这不是我的预期。

【问题讨论】:

  • 这能回答你的问题吗? Java Ordered Map
  • This one might also回答你的问题。
  • 您没有说明您在第三张地图中使用了哪种类型的Map,但HashMap 不起作用,因为HashMaps 没有顺序。您应该能够通过使用LinkedHashMap(按插入顺序维护条目)并按所需顺序单独插入项目来实现您想要的。
  • @Nicolas 由于您当前拥有的两个地图是 HashMap 对象,它们是无序地图,因此以特定顺序合并它们没有任何意义完全没有。
  • @Nicolas 你能自己尝试一下吗? StackOverflow 不是一个为我编写代码的网站。即使借助网络搜索,我所说的哪一部分您觉得自己难以克服?

标签: java collections java-8 hashmap java-stream


【解决方案1】:

正如@Andreas 所建议的,您可以并行迭代地图并到LinkedHashMap 以维持秩序,

Map<String, String> result = new LinkedHashMap<>();
Iterator<Map.Entry<String, String>> iter1 = map1.entrySet().iterator();
Iterator<Map.Entry<String, String>> iter2 = map2.entrySet().iterator();
while(iter1.hasNext() || iter2.hasNext()) {
    Map.Entry<String, String> e1 = iter1.next();
    Map.Entry<String, String> e2 = iter2.next();

    result.put(e1.getKey(), e1.getValue());
    result.put(e2.getKey(), e2.getValue());

}

如果两个地图的键都像 id1、id2、month1、month2,那么您可以使用自定义的Comparator 和数字进行排序,如下所示,

Comparator<Map.Entry<String, String>> comparator = Comparator.comparing(c -> c.getKey().replaceAll("^\\D+", ""))  ;
Map<String, String> collect = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream())
        .sorted(comparator)
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(oldValue, newValue) -> oldValue, LinkedHashMap::new));

【讨论】:

  • 非常感谢 Code_Mode,它真的很有帮助:)
  • 使用两个不同大小的地图时,您的第一个代码将失败。此外,它不能改变问题代码的HashMaps 开始时没有定义的迭代顺序这一事实。因此,生成的 LinkedHashMap 将记住未指定的顺序也无济于事。
  • OP 确认两个映射具有相同数量的键。但我同意你的第二点。
【解决方案2】:

要合并(交错)两个映射的内容,并行迭代它们并添加到LinkedHashMap,这样插入顺序就会保留。

  1. mergedMap 创建为LinkedHashMap

  2. 获取iterator1 作为map1条目 的迭代器

  3. 获取iterator2 作为map2条目 的迭代器

  4. 重复直到两个迭代器都结束:

    1. 如果没有结束,则从iterator1 获取下一个条目并添加到mergedMap

    2. 如果没有结束,则从iterator2 获取下一个条目并添加到mergedMap

就是这样。这里的所有都是它的。现在您只需要编写代码即可。

【讨论】:

    猜你喜欢
    • 2021-02-27
    • 2021-09-17
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多