我正在尝试删除值为null
的所有条目。代码是:
Map<String, String> map = new HashMap<>();
map.put("one", null);
map.put("two", null);
map.put("three", "THREE");
Iterator iterator = map.values().iterator();
while (iterator.hasNext())
{
if (iterator.next() == null) {
iterator.remove();
}
}
for (Map.Entry<String, String> e : map.entrySet()) {
System.out.println(e.getKey() + ":" + e.getValue());
}
我的问题是iterator
绑定到map.values
,为什么它可以删除整个条目?
答案 0 :(得分:8)
这是可能的,因为Map#values
会返回地图支持的值的视图。
返回此地图中包含的值的Collection视图。该集合由地图支持,因此对地图的更改将反映在集合中,反之亦然。 [...]该集合支持元素删除,它通过Iterator.remove,Collection.remove,removeAll,retainAll和clear操作从地图中删除相应的映射。它不支持add或addAll操作。
请注意,大多数地图实现扩展的AbstractMap
类都有一个额外的字段transient volatile Collection<V> values
,这正是您将在那里获得的。如您所见,集合在内部由Map使用,因此对它的更改也会反映在Map本身上。另见:Source code of AbstractMap
如果您想详细了解,请查看源代码中的AbstractMap#values
方法。在那里,他们创建 values -collection作为在原始地图上运行的包装器。例如,其next
方法会迭代地图的Entry<K, V>
条目,但只返回Entry#getValue
的值,依此类推。
如您所见,remove
方法也会被传递给Entry<K, V>
的迭代器,因此最终将在原始地图上执行删除。
答案 1 :(得分:2)
Zabuza已经给出了解释,但是因为有正确的方法来删除你的元素,我写了:
要删除值为Entry
的空值,您可以使用Streams
:
map = map.entrySet()
.stream()
.filter(entry -> entry.getValue()!=null)
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));
或单行:map.entrySet().removeIf(e -> e.getValue()==null);
或者:map.values().removeIf(v -> v == null)