Create a map from a list of maps

后端 未结 2 579
庸人自扰
庸人自扰 2020-12-06 12:00

I have a list of maps.

List>

The values in the list are, for example

<1, String1>
&l         


        
相关标签:
2条回答
  • 2020-12-06 12:40

    Have a look at guavas MultiMap. Should be exactly what you are looking for:

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

    0 讨论(0)
  • 2020-12-06 12:48

    You can do it the following with 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]
    Integer: 2 / List: [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:

    1. Obtain a Stream<Map<Integer, String>> from the mapList.
    2. Apply the flatMap operator, which roughly maps a stream into an already existing stream.
      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>>.
    3. I intend to collect the Stream<Map.Entry<Integer, String>> into a 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.
    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.
    6. At this point I would have had a Map<Integer, List<Map.Entry<Integer, String>>> if I had not done any extra processing.
    7. To ensure that I get the correct signature, I must add a downstream to the Collectors.groupingBy, which has to provide a collector.
    8. For this downstream I use a collector that maps my Map.Entry entries to their String values via the reference Map.Entry::getValue.
    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.
    10. And this is how we get a Map<Integer, List,String>>.
    0 讨论(0)
提交回复
热议问题