我想通过应用条件从HashMap中删除项目。请考虑以下代码:
Set<Foo> set = myMap.keySet();
Iterator<Foo> itr = set.iterator();
while (itr.hasNext())
{
Foo foo = itr.next();
if (foo.toString().length() < 3) {
myMap.remove(foo); //remove the pair if key length is less than 3
}
}
所以我得到了一个ConcurentModificationException,因为在迭代期间我正在修改HashMap。我该怎么办?有没有其他方法来搜索我的条件并在最后执行remove命令,以便我可以避免这种异常?
答案 0 :(得分:13)
使用itr.remove()
代替myMap.remove(o.toString())
答案 1 :(得分:4)
从Java 8开始,Collection提供了removeIf(Predicate<? super E>)
,它将删除给定谓词返回true的所有元素。问题中的示例可以重写为
myMap.keySet().removeIf(o -> o.toString().length() < 3);
Collection提供的默认实现使用迭代器并调用Iterator.remove
,但如果集合可以提供更好的实现,则集合可以覆盖它。更重要的是,使用removeIf
的代码更清晰,更简洁。
答案 2 :(得分:3)
如果要在迭代期间删除元素,则必须使用Iterator.remove()。否则,当前Iterator对象进入导致异常的不一致状态。当您知道密钥时,即在不迭代同一个Map时,可以使用Map.remove(key)。
此规则适用于所有集合(列表,集等)。
答案 3 :(得分:1)
是 - itr.remove()
从底层集合中移除迭代器返回的最后一个元素(可选操作)。每次调用next时,只能调用一次此方法。
Iterator
的{{1}}扩展了keySet()
,其HashIterator
方法调用remove()
如果你需要密钥和值,你也可以获得HashMap.this.removeEntryForKey(key);
- 它的迭代器具有相同的属性。
答案 4 :(得分:0)
要做你所描述的,我个人喜欢使用功能样式编程:
Map<String,Object> map = // obtained somehow;
Map<String,Object> filtered = Maps.filterKeys(map, new Predicate() {
@Override
public boolean apply(String input) {
return input.length() < 3;
}
});
代码段使用google集合库。它通过仅获取与提供的谓词匹配的那些条目来创建原始地图的视图。