【问题标题】:Create a map from a list of maps从地图列表创建地图
【发布时间】:2014-03-20 08:20:21
【问题描述】:

我有一张地图列表。

List<Map<Integer, String>>

列表中的值是,例如

<1, String1>
<2, String2>
<1, String3>
<2, String4>

作为最终结果,我想要一张地图>,比如

<1, <String1, String3>>
<2, <String2, String4>>

如何在 Java 中实现这一点。

代码:

List<Map<Integer, String>> genericList = new ArrayList<Map<Integer,String>>();
for(TrackActivity activity : activityMajor){
Map<Integer, String> mapIdResponse = activity.getMapIdResponse();
genericList.add(mapIdResponse);
}

现在这个 genericList 是输入,来自这个列表,基于我想要的相同 id

Map<Integer, List<String>> mapIdResponseList

基本上,将基于 id 的 String 响应组合在一起,将具有相同 id 的响应分组到一个列表中,然后创建一个以该 id 作为键和列表作为其值的新映射。

【问题讨论】:

  • Map&lt;Integer,&lt;String,String&gt;&gt;
  • 所以您在每个映射中只存储一个键值对?在我看来,自定义对象就足够了。
  • 我看到你想要Map&lt;Integer, List&lt;String&gt;&gt;
  • 列表中的地图有共同的键但不同的值。我想将这些公共值分组到一个列表中,然后将该列表放入一个新的 map> 中,其中公共键作为新映射中的键,而 list 作为它的值。
  • 您是否需要将&lt;String1, String3&gt; 放在一个对象中,或者也可以将它们放在List&lt;String&gt; 中?

标签: java hashmap


【解决方案1】:

您可以使用 Java 8 执行以下操作:

private void init() {
    List<Map<Integer, String>> mapList = new ArrayList<>();

    Map<Integer, String> map1 = new HashMap<>();
    map1.put(1, "String1");
    mapList.add(map1);

    Map<Integer, String> map2 = new HashMap<>();
    map2.put(2, "String2");
    mapList.add(map2);

    Map<Integer, String> map3 = new HashMap<>();
    map3.put(1, "String3");
    mapList.add(map3);

    Map<Integer, String> map4 = new HashMap<>();
    map4.put(2, "String4");
    mapList.add(map4);

    Map<Integer, List<String>> response = mapList.stream()
            .flatMap(map -> map.entrySet().stream())
            .collect(
                    Collectors.groupingBy(
                            Map.Entry::getKey, 
                            Collectors.mapping(
                                    Map.Entry::getValue, 
                                    Collectors.toList()
                            )
                    )
            );
    response.forEach((i, l) -> {
        System.out.println("Integer: " + i + " / List: " + l);
    });
}

这将打印:

整数:1 / 列表:[String1, String3]
整数:2 / 列表:[String2, String4]

解释(非常有根据),恐怕我无法解释每一个细节,您需要先了解Java 8中引入的StreamCollectors API的基础知识:

  1. mapList 获取Stream&lt;Map&lt;Integer, String&gt;&gt;
  2. 应用flatMap 运算符,它将一个流大致映射到一个已经存在的流。
    这里:我将所有Map&lt;Integer, String&gt; 转换为Stream&lt;Map.Entry&lt;Integer, String&gt;&gt; 并将它们添加到现有流中,因此现在它也是Stream&lt;Map.Entry&lt;Integer, String&gt;&gt; 类型。
  3. 我打算将Stream&lt;Map.Entry&lt;Integer, String&gt;&gt; 收集到Map&lt;Integer, List&lt;String&gt;&gt;
  4. 为此,我将使用Collectors.groupingBy,它基于分组函数生成Map&lt;K, List&lt;V&gt;&gt;,在这种情况下,FunctionMap.Entry&lt;Integer, String&gt; 映射到Integer
  5. 为此,我使用了一个方法引用,这正是我想要的,即Map.Entry::getKey,它在Map.Entry 上运行并返回一个Integer
  6. 如果我没有做任何额外的处理,此时我会得到一个Map&lt;Integer, List&lt;Map.Entry&lt;Integer, String&gt;&gt;&gt;
  7. 为确保我得到正确的签名,我必须向Collectors.groupingBy 添加一个下游,它必须提供一个收集器。
  8. 对于这个下游,我使用了一个收集器,它通过引用 Map.Entry::getValue 将我的 Map.Entry 条目映射到它们的 String 值。
  9. 我还需要指定如何收集它们,这里只是一个Collectors.toList(),因为我想将它们添加到列表中。
  10. 这就是我们获得Map&lt;Integer, List,String&gt;&gt; 的方式。

【讨论】:

    【解决方案2】:

    看看番石榴MultiMap。应该正是您正在寻找的:

    http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap

    【讨论】:

    • 谢谢,但我正在寻找一种方法来做到这一点,而无需添加额外的库。
    猜你喜欢
    • 2015-09-27
    • 2020-11-05
    • 2020-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-08
    相关资源
    最近更新 更多