简体   繁体   English

合并 Map <string, list<string> Java 8 Stream</string,>

[英]Merge Map<String, List<String> Java 8 Stream

I would like to merge two Map with JAVA 8 Stream:我想合并两个 Map 和 JAVA 8 Stream:

Map<String, List<String>> mapGlobal = new HashMap<String, List<String>>();
Map<String, List<String>> mapAdded = new HashMap<String, List<String>>();

I try to use this implementation:我尝试使用这个实现:

mapGlobal = Stream.of(mapGlobal, mapAdded)
                .flatMap(m -> m.entrySet().stream())
                .collect(Collectors.groupingBy(Map.Entry::getKey,
                        Collectors.mapping(Map.Entry::getValue,        
                                           Collectors.toList())
                ));

However, this implementation only create a result like:但是,此实现只会产生如下结果:

Map<String, List<Object>>

If one key is not contained in the mapGlobal , it would be added as a new key with the corresponding List of String.如果一个键不包含在mapGlobal中,它将作为一个新键添加到相应的字符串列表中。 If the key is duplicated in mapGlobal and mapAdded , both list of values will be merge as: A = {1, 3, 5, 7} and B = {1, 2, 4, 6} then A ∪ B = {1, 2, 3, 4, 5, 6, 7} .如果键在mapGlobalmapAdded中重复,则两个值列表将合并为: A = {1, 3, 5, 7}B = {1, 2, 4, 6}然后A ∪ B = {1, 2, 3, 4, 5, 6, 7}

You can do this by iterating over all the entries in mapAdded and merging them into mapGlobal .您可以通过迭代mapAdded所有条目并将它们合并到mapGlobal来做到这mapGlobal

The following iterates over the entries of mapAdded by calling forEach(action) where the action consumes the key and value of each entry.下面通过调用forEach(action)迭代mapAdded的条目,其中操作消耗每个条目的键和值。 For each entry, we call merge(key, value, remappingFunction) on mapGlobal : this will either create the entry under the key k and value v if the key didn't exist or it will invoke the given remapping function if they already existed.对于每个条目,我们在mapGlobal上调用merge(key, value, remappingFunction) mapGlobal :如果键不存在,这将在键k和值v下创建条目,或者如果它们已经存在,它将调用给定的重新映射函数。 This function takes the 2 lists to merge, which in this case, are first added to a TreeSet to ensure both unique and sorted elements and converted back into a list:此函数将 2 个列表合并,在这种情况下,首先将其添加到TreeSet以确保唯一和已排序的元素并转换回列表:

mapAdded.forEach((k, v) -> mapGlobal.merge(k, v, (v1, v2) -> {
    Set<String> set = new TreeSet<>(v1);
    set.addAll(v2);
    return new ArrayList<>(set);
}));

If you want to run that potentially in parallel, you can create a Stream pipeline by getting the entrySet() and calling parallelStream() on it.如果您想潜在地并行运行它,您可以通过获取entrySet()并在其上调用parallelStream()来创建一个 Stream 管道。 But then, you need to make sure to use a map that supports concurrency for mapGlobal , like a ConcurrentHashMap .但是,您需要确保对mapGlobal使用支持并发的mapGlobal ,例如ConcurrentHashMap

ConcurrentMap<String, List<String>> mapGlobal = new ConcurrentHashMap<>();
// ...
mapAdded.entrySet().parallelStream().forEach(e -> mapGlobal.merge(e.getKey(), e.getValue(), (v1, v2) -> {
    Set<String> set = new TreeSet<>(v1);
    set.addAll(v2);
    return new ArrayList<>(set);
}));

Using foreach over Map can be used to merge given arraylist.在 Map 上使用 foreach 可用于合并给定的数组列表。

    public Map<String, ArrayList<String>> merge(Map<String, ArrayList<String>> map1, Map<String, ArrayList<String>> map2) {
    Map<String, ArrayList<String>> map = new HashMap<>();
    map.putAll(map1);

    map2.forEach((key , value) -> {
        //Get the value for key in map.
        ArrayList<String> list = map.get(key);
        if (list == null) {
            map.put(key,value);
        }
        else {
            //Merge two list together
            ArrayList<String> mergedValue = new ArrayList<>(value);
            mergedValue.addAll(list);
            map.put(key , mergedValue);
        }
    });
    return map;
}

The original implementation doesn't create result like Map<String, List<Object>> , but Map<String, List<List<String>>> .原始实现不会创建像Map<String, List<Object>> ,而是Map<String, List<List<String>>> You need additional Stream pipeline on it to produce Map<String, List<String>> .您需要额外的 Stream 管道来生成Map<String, List<String>>

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

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

for(Map.Entry<String, List<String>> entry: map1.entrySet()) {
   result.put(entry.getKey(), new ArrayList<>(entry.getValue());
}

for(Map.Entry<String, List<String>> entry: map2.entrySet()) {
   if(result.contains(entry.getKey())){
       result.get(entry.getKey()).addAll(entry.getValue());
   } else {
       result.put(entry.getKey(), new ArrayList<>(entry.getValue());
   }

}

This solution creates independent result map without any reference to map1 and map2 lists.此解决方案创建独立的结果 map,而不引用 map1 和 map2 列表。

Using StreamEx使用StreamEx

Map<String, List<String>> mergedMap =
        EntryStream.of(mapGlobal)
                .append(EntryStream.of(mapAdded))
                .toMap((v1, v2) -> {
                    List<String> combined = new ArrayList<>();
                    combined.addAll(v1);
                    combined.addAll(v2);
                    return combined;
                });

If you have even more maps to merge just append to the stream如果您有更多地图要合并,只需附加到流

                .append(EntryStream.of(mapAdded2))
                .append(EntryStream.of(mapAdded3))
Here is the full code to Iterate Two HashMap which have values stored in the form of list. Merging all the key and values in first hashmap. Below is the example.

  HashMap<String, List<String>> hmap1 = new HashMap<>();
        List<String> list1 = new LinkedList<>();
        list1.add("000");
        list1.add("111");
        List<String> list2 = new LinkedList<>();
        list2.add("222");
        list2.add("333");
        hmap1.put("Competitor", list1);
        hmap1.put("Contractor", list2);
        //  System.out.println(hmap1);


        HashMap<String, List<String>> hmap2 = new HashMap<>();
        List<String> list3 = new LinkedList<>();
        list3.add("aaa");
        list3.add("bbb");
        List<String> list4 = new LinkedList<>();
        list4.add("ccc");
        list4.add("ddd");
        hmap2.put("Competitor", list3);
        hmap2.put("Contractor", list4);


//******* Java 8 Feature *****
 hmap1.forEach((k, v) -> hmap2.merge(k, v, (v1, v2) -> {
            List<String> li = new LinkedList<>(v1);
            li.addAll(v2);
            hmap2.put(k,li);
            return new ArrayList<>(li);
        }));
        System.out.println(hmap2);

Output - {Competitor=[aaa, bbb, 000, 111], Contractor=[ccc, ddd, 222, 333]}输出 - {竞争者=[aaa, bbb, 000, 111], 承包商=[ccc, ddd, 222, 333]}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用Java Stream将List和String列表转换为Map - Converting List of List and String to Map with Java Stream Java 8流到Map <Integer, List<String> &gt; - Java 8 stream to Map<Integer, List<String>> 用于 Map 的 Java 8 流过滤器<String, List<Object> &gt; - Java 8 stream filter for Map<String, List<Object>> Java 8流映射 <String, List<String> &gt;每个键的值总和 - Java 8 stream Map<String, List<String>> sum of values for each key java流列表 <Map<String,Double> &gt;需要基于字符串的平均值 - java stream List<Map<String,Double>> need average based on the string 如何将Stream <Map <String,Map <String,String >>>合并为单个Map <String,Map <String,String >>? - How to merge Stream<Map<String, Map<String, String>>> into a single Map<String, Map<String, String>>? 如何合并/合并列表的 Map 的两个 Map(地图<string, map<enum, list<string> &gt;&gt;) 在 Java 8</string,> - How do I Combine/Merge two Map of Map of Lists (Map<String, Map<Enum, List<String>>>) in Java 8 将List转换<A>为Map</a> <String,List<A> <A>&gt;使用java 8流API</a> - converting List<A> to Map<String,List<A>> using java 8 stream API 使用流将Java <Object>收集到Java 8中的Map <String,List <Object >> - Collect List<Object> to Map<String, List<Object>> in Java 8 using stream 如何使用Java 8 Stream从Map列表中的字符串中获取列表? - How to get a List from string from List of Map with Java 8 Stream?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM