简体   繁体   English

在2个HashMaps中查找不同的值

[英]Find the different values in 2 HashMaps

I have 2 HashMaps with millions of records. 我有2个HashMaps,有数百万条记录。 For simplicity, I will deal with only few records. 为简单起见,我将只处理几条记录。 I want to find the values which are in map a that are not in map b . 我想找到地图a中不在地图b Is there a function to do this? 有这个功能吗? What's the quickest way to go about it? 什么是最快捷的方式?

Map a = new HashMap();
a.put(1, "big");
a.put(2, "hello");
a.put(3, "world");

Map b = new HashMap();

b.put(1,"hello");
b.put(2, "world");

In this case, output should be "big" since it is in a and not in b . 在这种情况下,输出应该是"big"因为它在a而不在b

You are looking for the removeAll operation on the values of the map. 您正在寻找对地图值的removeAll操作。

public static void main(String[] args) {
    Map<Integer, String> a = new HashMap<>();
    a.put(1, "big");
    a.put(2, "hello");
    a.put(3, "world");

    Map<Integer, String> b = new HashMap<>();
    b.put(1,"hello");
    b.put(2, "world");

    a.values().removeAll(b.values()); // removes all the entries of a that are in b

    System.out.println(a); // prints "{1=big}"
}

values() returns a view of the values contained in this map: values()返回此映射中包含的值的视图:

Returns a Collection view of the values contained in this map. 返回此映射中包含的值的Collection视图。 The collection is backed by the map, so changes to the map are reflected in the collection, and vice-versa. 该集合由地图支持,因此对地图的更改将反映在集合中,反之亦然。

So removing elements from the values effectively removes the entries. 因此,从值中删除元素会有效地删除条目。 This is also documented: 这也记录在案:

The collection supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove , Collection.remove , removeAll , retainAll and clear operations. 该集合支持元素删除,它通过Iterator.removeCollection.removeremoveAllretainAllclear操作从地图中删除相应的映射。


This removes from the map in-place. 这将从地图中删除。 If you want to have a new map with the result, you should call that method on a new map instance. 如果要创建包含结果的新映射,则应在新映射实例上调用该方法。

Map<Integer, String> newMap = new HashMap<>(a);
newMap.values().removeAll(b.values());

Side-note: don't use raw types ! 旁注: 不要使用原始类型

The solution of @Tunaki will work fine, is readable and short. @Tunaki的解决方案可以正常工作,可读性和简短性。

Just for the sake of completeness the solution "by hand": 只是为了完整性,“手工”解决方案:

for (String s : a.values()) {
    if (!b.containsValue(s)) {
        System.out.println (s);
        // process the value (e.g. add it to a list for further processing)
    }
}

如果您被允许使用Apache Commons Collections 4,则可以使用SetUtils.difference() ,它可能与@Tinaki的答案具有相似的性能。

Here is a fast, non-destructive, solution based on streams: 这是一个基于流的快速,非破坏性的解决方案:

Map<Integer, String> a = ...;
Map<Integer, String> b = ...;
Set<String> bVal = new HashSet<String>(b.values());
String[] res = a.values()
    .stream()
    .filter(s -> bVal.contains(s))
    .toArray(String[]::new);

res contains all values present in both maps. res包含两个映射中存在的所有 Upon completion of this code both maps remain in their original state. 完成此代码后,两个映射都保持其原始状态。

The code requires additional memory of the size proportional to the size of the second map. 该代码需要额外的内存,其大小与第二个映射的大小成比例。 If one of your maps is significantly smaller than the other, you could save space by using the smaller map as map b in the example above. 如果您的某个地图明显小于另一个地图,则可以使用较小的地图作为上面示例中的地图b来节省空间。

Demo. 演示。

A.containsValue(value) && !B.containsValue(value)

请参阅: https//docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#containsValue(java.lang.Object)

I am assuming that the unique values u want does not depend on the key position (2, "hello" and 1,"hello") 我假设你想要的唯一值不依赖于关键位置(2,“你好”和1,“你好”)

A single line of code should do it. 单行代码应该这样做。

a.values().removeAll(b.values());

caution: this removes all the repeating values from 'a' hashmap 警告:这会从'a'散列图中删除所有重复值

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

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