如何对n个哈希映射使用java 8合并函数

nel*_*elz 8 java string java-8 java-stream

我需要在循环中理想地合并n个hashmap,如下所示,使用java 8 merge或者其他东西:

地图1: {Name:XXX,Phn:123,Work:""}

地图2: {Name:XXX,Phn:456,Work: xyz}

地图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
}
Run Code Online (Sandbox Code Playgroud)

当我尝试像这样使用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;
}
Run Code Online (Sandbox Code Playgroud)

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

Tun*_*aki 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))
            )
        ));
Run Code Online (Sandbox Code Playgroud)

此平面将每个地图映射到其条目的流中.然后,Stream按每个条目的值进行分组,所有具有相同键的不同元素将映射到它们的值,并将其连接起来.

通过首先收集a中的所有值,可以实现不同的部分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}"
}
Run Code Online (Sandbox Code Playgroud)