2010-11-28 113 views
3

嗨,我想通过应用条件从HashMap中删除项目。考虑这个代码:从HashMap,Java中删除项目问题?

Set set = myMap.keySet(); 
    Iterator itr = set.iterator(); 
    while (itr.hasNext()) 
    { 
     Object o = itr.next(); 
     if (o.toString().length() < 3) { 
      myMap.remove(o.toString()); //remove the pair if key length is less then 3 
    } 

所以我得到运行时ConcurentModification异常,因为在迭代期间我修改了HashMap。我该怎么办?有没有其他方法来搜索我的crieteria并在最后执行remove命令,以便我可以避免此异常?

+0

如果我使用try/catch块,在运行时程序卡在某处并且光标保持闪烁。我必须通过CTR + C终止程序C 有没有办法避免这种情况,仍然可以从HashMap中删除键/值对 – Mavin 2010-11-28 22:45:22

回答

12

使用itr.remove(),而不是myMap.remove(o.toString())

+0

您确定这有效吗?问题中的迭代器不是HashMap的迭代器,而是HashMap的密钥集的迭代器。 – sje397 2010-11-28 22:47:00

1

是 - itr.remove()

从底层collection中移除迭代器(可选操作)返回的最后一个元素。这种方法只能在下一次调用时调用一次。

keySet()Iterator扩展HashIterator,其remove()方法调用HashMap.this.removeEntryForKey(key);

您还可以得到entrySet()如果你需要同时得到键和值 - 它的迭代器具有相同的属性。

3

如果在迭代过程中删除元素,则必须改用Iterator.remove()。否则,当前Iterator对象进入导致异常的不一致状态。当你知道密钥时,你可以使用Map.remove(key),也就是说,当你没有遍历同一个Map时。

此规则适用于所有集合(列表,集合等)。

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; 
    } 
}); 

的代码片段使用了谷歌集合库。它通过仅仅使用与所提供的谓词匹配的键来创建原始映射的视图。

4

从Java 8开始,Collection提供了removeIf(Predicate<? super E>),它将删除给定谓词返回true的所有元素。在这个问题的例子可以改写为

myMap.keySet().removeIf(o -> o.toString().length() < 3); 

通过收集提供的默认实现使用一个迭代器,并呼吁Iterator.remove,但集合可以覆盖此,如果他们能够提供更好的实现。更重要的是,使用removeIf的代码更清晰,更简洁。