Java 8 Stream根据某个相同的key合并两个Map List,其他key相同时优先保留其中一个List的值

Posted treefornow

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 8 Stream根据某个相同的key合并两个Map List,其他key相同时优先保留其中一个List的值相关的知识,希望对你有一定的参考价值。

// ============== new两条源数据,加入list ==================

    Map<String, Object> map1 = new HashMap<>();
    map1.put("id", 1);
    map1.put("name", "甲");
    map1.put("age", 12);
    map1.put("gender", "男");
    Map<String, Object> map2 = new HashMap<>();
    map2.put("id", 2);
    map2.put("name", "乙");
    map2.put("age", 13);
    map2.put("gender", "女");
    List<Map<String, Object>> sourceList = new ArrayList<>();
    sourceList.add(map1);
    sourceList.add(map2);

    // ============== new三条新带并入的数据,加入list ==================
    Map<String, Object> newMap1 = new HashMap<>();
    newMap1.put("id", 1);
    newMap1.put("name", "甲");
    newMap1.put("age", 10);
    newMap1.put("birthday", "2011-09-29");
    Map<String, Object> newMap2 = new HashMap<>();
    newMap2.put("id", 2);
    newMap2.put("name", "乙");
    newMap2.put("age", 11);
    newMap2.put("birthday", "2010-09-29");
    Map<String, Object> newMap3 = new HashMap<>();
    newMap3.put("id", 3);
    newMap3.put("name", "丙");
    newMap3.put("age", 19);
    newMap3.put("birthday", "2002-09-29");
    List<Map<String, Object>> newList = new ArrayList<>();
    newList.add(newMap1);
    newList.add(newMap2);
    newList.add(newMap3);
    /**
     * sourceList有两条数据,newList有三条数据
     * 我们想要的效果是将两个mapList合并,尽量保留各自所有数据,遇到id相同的map则合并,
     * 当出现其他key相同的情况时,sourceList中有值就优先用sourceList中的值,
     * 如果同一个key,sourceList的值为空,此时再用newList中的值
     * (上面例子中name和age是key冲突的,name两个list均相同,但age不同)
     * 并且最终合并成一个mapList,达到如下效果:
     * [{"birthday":"2011-09-29","gender":"男","name":"甲","id":1,"age":12},
     * {"birthday":"2010-09-29","gender":"女","name":"乙","id":2,"age":13},
     * {"birthday":"2002-09-29","name":"丙","id":3,"age":19}]
     */
    //一般实际开发中前面的两个List都是数据库查询出来而不是手动new出来的,就可能会有List为空的情况,为避免空指针异常不能直接用sourceList来addAll newList
    // 所以这里要手动New一个合并的list
    List<Map<String, Object>> list = new ArrayList<>();
    list.addAll(sourceList);
    list.addAll(newList);
    //合并
    List<Map<String,Object>> combine = list.stream()
            .collect(Collectors.groupingBy(group -> group.get("id").toString())) // 根据map中id的value值进行分组, 这一步的返回结果Map<String,List<Map<String, Object>>>
            .entrySet() // 得到Set<Map.Entry<String, List<Map<String, Object>>>
            .stream()
            .map(m -> { // 进入映射环境
                // m.getValue()的结果是 List<Map<String, Object>>
                Map<String, Object> collect = m.getValue().stream()
                        // o.entrySet() 的结果是 Set<Map.Entry<String, Object>>
                        .flatMap(o -> o.entrySet().stream()).filter(e -> e.getValue() != null)//过滤下,value需要是不为空的,否则报错
                        // (m1, m2) -> m1 的意思是如果key相同 m1 == m2 则value使用m1(此处为sourceList中的值)
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (m1, m2) -> m1
                        ));
                return collect;
            }).sorted(Comparator.comparing(m -> m.get("id").toString())).collect(Collectors.toList());
    
    //打印输出看看
    System.out.println(JSON.toJSONString(combine));
    
    本文相关参考链接:https://segmentfault.com/q/1010000010380854

以上是关于Java 8 Stream根据某个相同的key合并两个Map List,其他key相同时优先保留其中一个List的值的主要内容,如果未能解决你的问题,请参考以下文章

js 数组对象根据相同value的key合并两个对象

javascript 数组对象根据相同属性值{key:value}合并两个对象

list去重+Java8-Stream distinct 根据list某个字段去重

Java 8 Stream 映射调用字符串与合并为一个 [重复]

使用 Java 8 Stream API 合并两个 Map<String, Integer>

List集合中的对象根据某个相同的属性,合并另外属性