用 Java 8 合并两张地图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40158605/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:27:48  来源:igfitidea点击:

Merge two maps with Java 8

javajava-stream

提问by dardy

I have two maps like this:

我有两张这样的地图:

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

MyObject {
   Integer mark1;
   Integer mark2;
}

What I want to do to is to merge the two maps into a map3<String, MyObject>like this:

我想要做的是将两张地图合并成一个map3<String, MyObject>这样的:

  1. If map1.placeis not in map2.place, then I add the entry to map3.
  2. same if map2.placeis not in map1.place, I add the entry to map3.
  3. if map1.placeis in map2.place, then I add this entry:
    • map1.place, (map1.mark1, map2.mark2)
  1. 如果map1.place不在 中map2.place,那么我将条目添加到map3.
  2. 如果map2.place不在 中map1.place,我将条目添加到map3.
  3. 如果map1.placemap2.place,那么我添加这个条目:
    • map1.place, (map1.mark1, map2.mark2)

I have read about flatMap, but I really have a hard time using it. Any clue how to do this?
Thanks!!

我读过关于flatMap,但我真的很难使用它。任何线索如何做到这一点?
谢谢!!

采纳答案by Ash

Here is what I think would work

这是我认为可行的方法

Map<String, MyObj> map3 = new HashMap<>(map1);
map2.forEach(
    (key, value) -> map3.merge(key, value, (v1, v2) -> new MyObject(v1.mark1,v2.mark2))
);

The merge function is what is taking care of your scenario 3, in that if the key already exists, it creates a new MyObject with v1.mark1 and v2.mark2

合并函数负责处理您的场景 3,因为如果键已经存在,它会创建一个带有 v1.mark1 和 v2.mark2 的新 MyObject

回答by talex

Something like this should work.

像这样的事情应该有效。

Map<String, MyObject> result = new HashMap<String, MyObject>();

Set<String> allKeys = new HashSet<String>();
allKeys.addAll(map1.keySet());
allKeys.addAll(map2.keySet());
for(String key : allKeys){
    MyObject v1 = map1.get(key);
    MyObject v2 = map2.get(key);
    if(v1 != null && v2 == null){
        result.put(key, v1);
    }else if(v1 == null && v2 !=null){
        result.put(key, v2);
    } else {
        MyObject newObject = new MyObject(v1.mark1, v2.mark2); 
        result.put(key, newObject);
    }
}

回答by Jerin Joseph

Incase of a simple merge you could use map3.putAll()as explained in How can I combine two HashMap objects containing the same types?

如果您可以使用简单的合并,map3.putAll()如何组合包含相同类型的两个 HashMap 对象中所述?

In your case, you would probably have to write some custom logic,

在您的情况下,您可能需要编写一些自定义逻辑,

First populate map3 with map1. Then Iterate the map3 to find any duplicates with map2 in which case you replace the entry with the map1.place, (map1.mark1, map2.mark2)logic.

首先用 map1 填充 map3。然后迭代 map3 以使用 map2 查找任何重复项,在这种情况下,您将条目替换为map1.place, (map1.mark1, map2.mark2)逻辑。

MapMerge

地图合并

public class MapMerge {

    public static void main(String []args){


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

        map3.putAll(map1);

        for(Entry<String, MyObject> entry:map2.entrySet()){         
            if (map3.containsKey(entry.getKey())){                  
                MyObject map3Obj = map3.get(entry.getKey());
                map3.put(
                    entry.getKey(), 
                    new MyObject(map3Obj.getMark1(),entry.getValue().getMark2())
                );
            }
        }
    }
}

MyObject

我的对象

class MyObject{

    public MyObject(Integer m1, Integer m2){
        mark1 = m1;
        mark2 = m2;
    }

    public Integer getMark1() {
        return mark1;
    }
    public void setMark1(Integer mark1) {
        this.mark1 = mark1;
    }
    public Integer getMark2() {
        return mark2;
    }
    public void setMark2(Integer mark2) {
        this.mark2 = mark2;
    }
    Integer mark1;
    Integer mark2;
}

回答by Nicolas Filotto

It can be done using the Stream APIwith the appropriate mergeFunctionas next:

可以使用Stream API适当的方法来完成,mergeFunction如下所示:

Map<String, MyObject> map3 = Stream.of(map1, map2)
    .flatMap(map -> map.entrySet().stream())
    .collect(
        Collectors.toMap(
            Map.Entry::getKey,
            Map.Entry::getValue,
            (v1, v2) -> new MyObject(v1.getMark1(), v2.getMark2())
        )
    );

This concatenates entries of map1followed by the entries of map2, then convert everything as a Mapwith a merge function that will use mark1from the first value (the one from map1) and mark2from the second value (the one from map2) in case of duplicate keys.

这连接了 的条目,map1然后是 的条目map2,然后Map使用合并函数将所有内容转换为 a ,该函数将使用mark1第一个值(来自 的值map1)和 mark2第二个值(来自 的值map2),以防出现重复键。



Or it could also be done using a different Supplier<Map>that will propose a map that already contains the entries of map1then we can focus only on adding the entries of map2as next:

或者也可以使用不同的方法来完成Supplier<Map>,它会提出一个已经包含条目的映射,map1那么我们可以只专注于添加如下条目map2

Map<String, MyObject> map3 = map2.entrySet()
    .stream()
    .collect(
        Collectors.toMap(
            Map.Entry::getKey,
            Map.Entry::getValue,
            (v1, v2) -> new MyObject(v1.getMark1(), v2.getMark2()),
            () -> new HashMap<>(map1)
        )
    );

回答by Soudipta Dutta

Case 1: Given a List of Maps. Then Join the maps according to the Key

案例 1:给定地图列表。然后根据Key加入地图

    public class Test14 {

        public static void main(String[] args) {

            Map<String, List<Integer>> m1 = new HashMap<>();
            Map<String, List<Integer>> m2 = new HashMap<>();
            m1.put("a", List.of(1));
            m1.put("b", List.of(2, 3));
            m2.put("a", List.of(12, 115));
            m2.put("b", List.of(2, 5));
            m2.put("c", List.of(6));

            System.out.println("map1 => " + m1);
            System.out.println("map2 => " + m2);

            ArrayList<Map<String, List<Integer>>> maplist = new ArrayList<Map<String, List<Integer>>>();
            maplist.add(m1);
            //   map1 => {a=[1], b=[2, 3]}
            maplist.add(m2);
            //      map2 => {a=[12, 115], b=[2, 5], c=[6]}

            System.out.println("maplist => " + maplist);
         //    maplist => [{a=[1], b=[2, 3]}, {a=[12, 115], b=[2, 5], c=[6]}]


            //  flatmap does omitted {} 
            List<Entry<String, List<Integer>>> collect11 = 
                    maplist
                    .stream()
                    .flatMap(map -> map.entrySet().stream())
                    .collect(Collectors.toList());
            System.out.println(" collect11  => " + collect11);
            // collect11  => [a=[1], b=[2, 3], a=[12, 115], b=[2, 5], c=[6]]

            // That's why we will use this flatmap


            Map<String, List<Integer>> map2 = maplist.stream()
            .flatMap(map -> map.entrySet().stream())

            .collect(
                    Collectors.toMap(
                            //keyMapper 
                            Map.Entry::getKey,


                            //valueMapper
                            Map.Entry::getValue,

                            (list_a,list_b) -> Stream.concat(list_a.stream(), list_b.stream())
                            .collect(Collectors.toList())


                            )//tomap

                    );
//{a=[1, 12, 115], b=[2, 3, 2, 5], c=[6]}

            System.out.println("After joining the maps according the key  => " + map2);
            // After joining the maps according the key  => {a=[1, 12, 115], b=[2, 3, 2, 5], c=[6]}

            /*
             OUTPUT :

             After joining the maps according the key  => {a=[1, 12, 115], b=[2, 3, 2, 5], c=[6]}
             */

        }// main

    }