简体   繁体   English

Java:合并两个哈希图?

[英]Java: Merge two hashmaps?

I have tried to implement my own merge function but it is getting more and more complicated and have more and more error. 我已经尝试实现自己的合并功能,但是合并功能越来越复杂,错误也越来越多。 I was thinking maybe Java already have this function since it seems like a common development problem. 我以为Java似乎已经具有此功能,因为这似乎是一个常见的开发问题。

Imagine I have two HashMaps<String, int> : 想象一下,我有两个HashMaps<String, int>

 HM1.put(foo,1)
 HM1.put(bar,1)

 HM2.put(foo,1)
 HM2.put(main,1)

When they are merged, the new HM2 will be something like this: 合并后,新的HM2将如下所示:

 [foo: 2]
 [bar, 1]
 [main,1]

You can iterate through the second map and update HM1 dynamically: 您可以遍历第二张地图并动态更新HM1:

HM2.entrySet()
   .forEach(entry -> HM1.compute(
            entry.getKey(),
            (key, value) -> value == null ? 
                            entry.getValue() : 
                            entry.getValue() + value));

EDIT : 编辑
Better use .merge (suggested by lexicore in this comment ), which avoids unnecessary runs of the compute function for absent keys: 更好地使用.merge (由lexicore在此注释中建议),这样可以避免在缺少键的情况下不必要运行计算功能:

HM2.entrySet()
   .forEach(entry -> HM1.merge(
            entry.getKey(),
            entry.getValue(),
            (key, value) -> entry.getValue()   + value));

Either of the above will update HM1 to have the final result. 以上任何一种都会更新HM1以得到最终结果。

System.out.println(HM1);

Outpus: 输出:

{bar=1, foo=2, main=1}

Here's a stream/collector-based solution. 这是基于流/收集器的解决方案。 It turns maps into streams of entries, concatenates them and then collects into a map, using entry keys as keys and summing values as int s. 它使用入口键作为键,将值求和为int ,将地图转换成条目流,将它们连接起来,然后收集到地图中。

    Map<String, Integer> HM1 = new HashMap<>();
    Map<String, Integer> HM2 = new HashMap<>();
    HM1.put("foo", 1);
    HM1.put("bar", 1);

    HM2.put("foo", 1);
    HM2.put("main", 1);

    Map<String, Integer> result = Stream
        .concat(HM1.entrySet().stream(), HM2.entrySet().stream())
        .collect(
                Collectors.groupingBy(
                        Map.Entry::getKey,
                        Collectors.summingInt(Map.Entry::getValue)));

hope, this will help you 希望这个能对您有所帮助

Set<String> keySet=hashMap1.keySet();

for(String str: keySet){
    int value=hashMap1.get(str);
    if(hashMap2.containsKey(str)){
        hashMap2.put(str, hashMap2.get(str)+value);
    }
    else{
        hashMap2.put(str, value);
    }
}

Map.merge() , as used above, is wrong. 上面使用的Map.merge()是错误的。 Remapping function there should be 重映射功能应该有

(oldvalue, newvalue) -> oldvalue + newvalue

Interestingly enough, the original author mistook 2 * 1 , as implemented by him, for 1 + 1 . 有趣的是,原始作者将他实施的2 * 1误认为1 + 1 Hey, the result is what I want, right? 嘿,结果就是我想要的,对吧? Lesson learnt, 1 is not a good test value. 经验教训,1不是一个好的测试值。

Another way to accomplish this is by using the toMap Collector , which is defined to take a merge function: 实现此目的的另一种方法是使用toMap Collector ,它被定义为采用合并功能:

var hm1 = new HashMap<String, Integer>();
hm1.put("foo",1);
hm1.put("bar",2);
var hm2 = new HashMap<String, Integer>();
hm2.put("foo",4);
hm2.put("baz",8);
var v = Stream.of(hm1, hm2)
    .map(Map::entrySet)
    .flatMap(Set::stream)
    .collect(
        Collectors.toMap(
            Map.Entry::getKey,   // key mapper
            Map.Entry::getValue, // value mapper
            Integer::sum         // merge function
        )
    );
System.out.println(v);

Output: 输出:

{bar=2, foo=5, baz=8} {bar = 2,foo = 5,baz = 8}

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM