比较两个地图并删除具有相同键或相同值的所有元素

问题描述:

我有两个需要比较的地图并将它们合并到结果地图中。我需要删除所有具有相同键或相同值的元素。比较两个地图并删除具有相同键或相同值的所有元素

基本上,说我有两个地图:

Map<String, String> map1 = new HashMap<>(); 
map1.put("1", "A"); 
map1.put("2", "A"); 
map1.put("3", "B"); 
map1.put("4", "C"); 
map1.put("5", "D"); 
map1.put("6", "E"); 

Map<String, String> map2 = new HashMap<>(); 
map2.put("1", "B"); 
map2.put("2", "A"); 
map2.put("4", "F"); 
map2.put("6", "C"); 
map2.put("7", "G"); 
map2.put("8", "H"); 

我需要删除所有具有或者相同的密钥或相同的价值观和需要保留背部只有双向唯一条目的条目。所以合并后,我需要有以下结果的地图,其中每个键映射到一个独特的价值和每一个值都有一个唯一的关键:

("5", "D"), ("7", "G"), ("8", "H") 

什么是Java中做到这一点的最好方法是什么?

我会创建一个包含从MAP1和MAP2所有值和键另一张图,然后我会去通过一个循环删除重复键和值

Map<String, String> map3 = new HashMap<>(); 
map3.putAll(map1); 
map3.putAll(map2); 

for(String a: map1.keySet()){ 
    if(map2.containsKey(a) || map2.containsValue(map1.get(a))){ 
     map3.remove(a); 
    } 
} 

希望这是很有用的!

+0

你应该迭代map3键! – Lake

+0

然后,我将有一个'java.util.ConcurrentModificationException'错误,因为我从map3中删除了元素 – tumisma

+0

啊,真的!你也许应该使用带有.remove()方法的Iterator然后..但现在我意识到它可以,就像它是 – Lake

下面的代码将做到这一点

Map map3 = new HashMap<>(map1); 
    map3.keySet().removeAll(map2.keySet()); 
    map3.values().removeAll(map2.values()); 
    map2.keySet().removeAll(map1.keySet()); 
    map2.values().removeAll(map1.values());  
    map3.putAll(map2); 
    System.out.println(map3); 

这将导致{7=G, 5=D, 8=H}

+0

谢谢。这似乎工作!我会给它一个! – Kathy

有趣的问题。我想不出一种特别干净的方式,但这里有一个使用Java 8的潜在解决方案 - 我很确定它可以被简化。我不喜欢这些有状态的操作,但我能看到的避免这种操作的唯一方法是将它分成两个操作。

Set<Map.Entry<String, String>> values = new HashSet<>(); 
Map<String,String> mergedMap = 
    Stream.concat(map1.entrySet().stream(), map2.entrySet().stream) 
    .filter(e -> !values.keySet().contains(e.getKey())) 
    .filter(e -> !values.valueSet().contains(e.getValue())) 
    .peek(e -> values.add(e)) 
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));