我有2个拥有数百万条记录的HashMaps。为简单起见,我将只处理几条记录。我想找到地图a
中不在地图b
中的值。有这个功能吗?什么是最快捷的方式?
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");
在这种情况下,输出应为"big"
,因为它位于a
而非b
。
答案 0 :(得分:10)
您正在寻找关于地图值的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()
返回此地图中包含的值的视图:
返回此地图中包含的值的
Collection
视图。该集合由地图支持,因此对地图的更改将反映在集合中,反之亦然。
因此,从值中删除元素会有效地删除条目。这也记录在案:
该集合支持元素删除,它通过
Iterator.remove
,Collection.remove
,removeAll
,retainAll
和clear
操作从地图中删除相应的映射
这将从地图中删除。如果您想要一个包含结果的新地图,您应该在新的地图实例上调用该方法。
Map<Integer, String> newMap = new HashMap<>(a);
newMap.values().removeAll(b.values());
答案 1 :(得分:2)
@Tunaki的解决方案可以正常工作,可读性和简短。
只是为了完整性解决方案&#34;手工&#34;:
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)
}
}
答案 2 :(得分:2)
如果你被允许使用Apache Commons Collections 4,你可以使用SetUtils.difference(),这可能与@Tinaki的答案有相似的表现。
答案 3 :(得分:1)
这是一种基于流的快速,非破坏性的解决方案:
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
包含两个地图中的所有值。完成此代码后,两个地图都保持原始状态。
代码需要额外的内存大小与第二个映射的大小成比例。如果您的某个地图明显小于另一个地图,则可以通过在上面的示例中将较小的地图用作地图b
来节省空间。
答案 4 :(得分:0)
A.containsValue(value) && !B.containsValue(value)
请参阅:https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#containsValue(java.lang.Object)
答案 5 :(得分:0)
我假设你想要的唯一值不依赖于关键位置 (2,“你好”和1,“你好”)
单行代码应该这样做。
a.values().removeAll(b.values());
警告:这会删除'a'hashmap
中的所有重复值