如何使用Java 8合并函数来合并n个哈希映射

8
我需要合并n个哈希表,最好使用Java 8的merge方法或类似方法进行循环合并,示例如下:
Map 1:{Name:XXX,Phn:123,Work:""} Map 2:{Name:XXX,Phn:456,Work: xyz} Map 3:{Name:XXX,Phn:789,Work:""} 我想要得到以下输出结果:
{
   Name:XXX,        // if all values for a key are same take one
   Phn:123/456/789  // merge all non null values for same key
   Work:xyz         // make sure non-null values are never replaced
}

当我尝试像这样使用putall时:
public Map<String,String> mergeOriginalDataMaps(List<Integer> indexList, List<Map<String,String>> originalData) {   
    Map<String,String> tmpMap = new HashMap<String,String> ();
    for (int index : indexList ) {
        tmpMap.putAll(originalData.get(index));
    }
    return tmpMap;
}

如果重复键的值是"",则先前的值将被新值替换。我需要连接这些值而不是替换它们。

1
123/456/789 是什么意思?你想要一个 Map<String, List<String>> 作为结果吗? - Tunaki
2
看起来你应该使用一个自定义类,其中包含3个字段namephonework,而不是使用HashMap - Paul Boddington
它不是特定的...我正在尝试读取用户输入文件内容,字段可以是任何东西... - nelz
1
@nelz 好的,说得也有道理,但是你需要解释如何处理不同的键吗?你只想连接 "Phn" 值吗? - Paul Boddington
我需要对所有重复的键执行此操作...只是我需要获取所有非空值并将它们连接起来。 - nelz
显示剩余3条评论
1个回答

9
如果你有一个List<Map<String, String>>,它表示要合并的地图列表,你可以使用以下方法:
Map<String, String> result =
    maps.stream()
        .flatMap(m -> m.entrySet().stream())
        .collect(Collectors.groupingBy(
            Map.Entry::getKey,
            Collectors.mapping(
                Map.Entry::getValue,
                Collectors.collectingAndThen(Collectors.<String>toSet(), s -> String.join("", s))
            )
        ));

这个示例将每个map映射成其条目的Stream。然后,该Stream按每个条目的值进行分组,并将所有具有相同键的不同元素映射到它们的值并连接在一起。
首先将所有值收集到Set中,才有可能实现去重部分。
示例代码:
public static void main(String[] args) {
    List<Map<String, String>> maps = new ArrayList<>();
    maps.add(new HashMap<String, String>(){{ put("Name", "XXX"); put("Phn", "123"); put("Work", ""); }});
    maps.add(new HashMap<String, String>(){{ put("Name", "XXX"); put("Phn", "456"); put("Work", "xyz"); }});
    maps.add(new HashMap<String, String>(){{ put("Name", "XXX"); put("Phn", "789"); put("Work", ""); }});

    Map<String, String> result =
        maps.stream()
            .flatMap(m -> m.entrySet().stream())
            .collect(Collectors.groupingBy(
                Map.Entry::getKey,
                Collectors.mapping(
                    Map.Entry::getValue,
                    Collectors.collectingAndThen(Collectors.<String>toSet(), s -> String.join("", s))
                )
            ));

    System.out.println(result); // prints "{Phn=123456789, Work=xyz, Name=XXX}"
}

哇...非常感谢...让我试着这样实现它!! - nelz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接