简体   繁体   English

从地图列表中创建地图

[英]Create a map from a list of maps

I have a list of maps. 我有一张地图清单。

List<Map<Integer, String>>

The values in the list are, for example 例如,列表中的值

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

As an end result, I want a Map>, like 作为最终结果,我想要一个Map>,就像

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

How can I achieve this in Java. 我怎样才能在Java中实现这一点。

CODE : 代码:

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

Now this genericList is the input and from this list, based on the same ids I want a 现在这个genericList是输入,从这个列表,基于我想要的相同ID

Map<Integer, List<String>> mapIdResponseList

Basically, to club the responses which are String based on the ids, grouping the responses with same id in a list and then creating a new map with that id as the key and the list as its value. 基本上,要根据ID对String的响应进行分组,在列表中对具有相同id的响应进行分组,然后创建一个以id作为键并将列表作为其值的新映射。

You can do it the following with Java 8: 您可以使用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);
    });
}

This will print: 这将打印:

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

Explanation (heavily warranted), I am afraid I cannot explain every single detail, you need to understand the basics of the Stream and Collectors API introduced in Java 8 first: 解释(严重保证),我恐怕无法解释每一个细节,您需要先了解Java 8中引入的StreamCollectors API的基础知识:

  1. Obtain a Stream<Map<Integer, String>> from the mapList . mapList获取Stream<Map<Integer, String>>
  2. Apply the flatMap operator, which roughly maps a stream into an already existing stream. 应用flatMap运算符,该运算符将流粗略地映射到已存在的流中。
    Here: I convert all Map<Integer, String> to Stream<Map.Entry<Integer, String>> and add them to the existing stream, thus now it is also of type Stream<Map.Entry<Integer, String>> . 这里:我将所有Map<Integer, String>转换为Stream<Map.Entry<Integer, String>>并将它们添加到现有流中,因此它现在也是Stream<Map.Entry<Integer, String>>
  3. I intend to collect the Stream<Map.Entry<Integer, String>> into a Map<Integer, List<String>> . 我打算将Stream<Map.Entry<Integer, String>>收集到Map<Integer, List<String>>
  4. For this I will use a Collectors.groupingBy , which produces a Map<K, List<V>> based on a grouping function, a Function that maps the Map.Entry<Integer, String> to an Integer in this case. 为此,我将使用一个Collectors.groupingBy ,其产生的Map<K, List<V>>基于分组功能,一个Function是,映射Map.Entry<Integer, String>到一个Integer在这种情况下。
  5. For this I use a method reference, which exactly does what I want, namely Map.Entry::getKey , it operates on a Map.Entry and returns an Integer . 为此,我使用了一个方法引用,它完全符合我的要求,即Map.Entry::getKey ,它在Map.Entry并返回一个Integer
  6. At this point I would have had a Map<Integer, List<Map.Entry<Integer, String>>> if I had not done any extra processing. 此时我会有一个Map<Integer, List<Map.Entry<Integer, String>>>如果我没有做任何额外的处理。
  7. To ensure that I get the correct signature, I must add a downstream to the Collectors.groupingBy , which has to provide a collector. 为了确保我获得正确的签名,我必须向Collectors.groupingBy添加一个下游,它必须提供一个收集器。
  8. For this downstream I use a collector that maps my Map.Entry entries to their String values via the reference Map.Entry::getValue . 对于这个下游,我使用一个收集器,通过引用Map.Entry::getValue将我的Map.Entry条目映射到它们的String值。
  9. I also need to specify how they are being collected, which is just a Collectors.toList() here, as I want to add them to a list. 我还需要指定它们的收集方式,这里只是一个Collectors.toList() ,因为我想将它们添加到列表中。
  10. And this is how we get a Map<Integer, List,String>> . 这就是我们如何获得Map<Integer, List,String>>

Have a look at guavas MultiMap. 看看guavas MultiMap。 Should be exactly what you are looking for: 应该是你正在寻找的:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM