Reputation: 77
I have 2 HashMaps with millions of records. 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
. 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
.
Upvotes: 4
Views: 1067
Reputation: 101
I am assuming that the unique values u want does not depend on the key position (2, "hello" and 1,"hello")
A single line of code should do it.
a.values().removeAll(b.values());
caution: this removes all the repeating values from 'a' hashmap
Upvotes: 0
Reputation: 726559
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. 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.
Upvotes: 1
Reputation: 137084
You are looking for the removeAll
operation on the values of the map.
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:
Returns a
Collection
view of the values contained in this map. 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
andclear
operations.
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!
Upvotes: 10
Reputation: 1016
If you're allowed to use Apache Commons Collections 4, you can use SetUtils.difference(), which probably has similar performance to @Tunaki's answer.
Upvotes: 2
Reputation: 4430
The solution of @Tunaki will work fine, is readable and short.
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)
}
}
Upvotes: 2
Reputation: 2352
A.containsValue(value) && !B.containsValue(value)
See: https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#containsValue(java.lang.Object)
Upvotes: 0