map遍历删除数据报错 | Java Debug 笔记

275 阅读1分钟

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看<活动链接>

遍历并从map中移除重复数据

  1. 具体问题已经在这个链接回答了 Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
  2. 如下代码
for (Object key : map.keySet())
    if (something)
        map.remove(key);
  • 程序执行会抛出ConcurrentModificationException异常。所以我对上面的代码做了一下修改
for (Object key : new ArrayList<Object>(map.keySet()))
    if (something)
        map.remove(key);
  • 当然这段代码是在synchronized 同步块中。
  • 还有更好的方案吗?我们看看评论区是如何回答的。

回答1

  • 这两个方法我并没有看出有什么不同。也许我还是不理解你表达的意思。你可以贴出你的最新的代码吗?
  • 笔者这里也是没有看懂。为什么第二段代码加上同步块就可以不报错了。

回答2

  • 如果你是java8+ ,你可以使用map.entrySet().removeIf(e -> <boolean expression>); 来实现你的功能。
  • map.values和map.keySet()同样也都支持这个removeIf方法。
  • removeIf在map.values()上的行为是什么?它删除指向该值的所有key->val元素

回答3

  • 这是实现代码
Map<String, String> map = new HashMap<String, String>() {
  {
    put("test", "test123");
    put("test2", "test456");
  }
};

for(Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); it.hasNext(); ) {
    Map.Entry<String, String> entry = it.next();
    if(entry.getKey().equals("test")) {
        it.remove();
    }
}
  • 你通过it.remve而不是通过collection.remve这个在循环里还是很明智的。
  • 当然这个前提是你使用的是Java及其以上版本。

回答4

Iterator<Object> it = map.keySet().iterator();

while (it.hasNext())
{
  it.next();
  if (something)
    it.remove();
 }
  1. 事实上你可以使用迭代器来实现删除的功能。这样就不会报错了。因为迭代器对重构没有要求。

个人总结

  • 不管是map还是list在循环中是不能够改变结构的。因为在内部是会统计重构的次数的。再循环中如果改变了就会抛出异常。

加油