Java ConcurrentModificationException从迭代器中删除元素

Java ConcurrentModificationException从迭代器中删除元素,java,iterator,Java,Iterator,从映射中删除条目时返回ConcurrentModificationException,但我看不出有什么问题 Iterator<String> mapIterator = this.attributeMap.keySet().iterator(); while (mapIterator.hasNext()) { String attributeName = mapIterator.next(); if (attributeName

从映射中删除条目时返回ConcurrentModificationException,但我看不出有什么问题

    Iterator<String> mapIterator = this.attributeMap.keySet().iterator();
    while (mapIterator.hasNext())
    {
        String attributeName = mapIterator.next();
        if (attributeName.matches(pattern))
        {
            mapIterator.remove();
        }
    }
Iterator-mapIterator=this.attributeMap.keySet().Iterator();
while(mapIterator.hasNext())
{
字符串attributeName=mapIterator.next();
if(attributeName.matches(模式))
{
mapIterator.remove();
}
}

您可以查看有关CME的一些详细信息:

当对象的并发修改不允许时,检测到该修改的方法可能会引发此异常。 例如,通常不允许一个线程在另一个线程迭代集合时修改集合。通常,在这些情况下,迭代的结果是未定义的。如果检测到此行为,某些迭代器实现(包括JRE提供的所有通用集合实现)可能会选择抛出此异常。这样做的迭代器称为fail-fast迭代器,因为它们快速、干净地失败,而不是在将来的不确定时间冒任意、不确定行为的风险

以下是Baeldung提供的一些解决方案,链接如下:

  • 直接使用迭代器
  • 在迭代过程中不删除
  • 使用removeIf()
  • 使用流进行过滤
  • 您可以查看他的网站,了解每个解决方案的详细信息,以避免CME:


    希望这有帮助。

    您可以查看有关CME的一些详细信息:

    当对象的并发修改不允许时,检测到该修改的方法可能会引发此异常。 例如,通常不允许一个线程在另一个线程迭代集合时修改集合。通常,在这些情况下,迭代的结果是未定义的。如果检测到此行为,某些迭代器实现(包括JRE提供的所有通用集合实现)可能会选择抛出此异常。这样做的迭代器称为fail-fast迭代器,因为它们快速、干净地失败,而不是在将来的不确定时间冒任意、不确定行为的风险

    以下是Baeldung提供的一些解决方案,链接如下:

  • 直接使用迭代器
  • 在迭代过程中不删除
  • 使用removeIf()
  • 使用流进行过滤
  • 您可以查看他的网站,了解每个解决方案的详细信息,以避免CME:

    希望这有帮助。

    在这种情况下 mapIterator.next() 抛出ConcurrentModificationException

    这背后的原因是:
    有一个
    int
    变量
    modCount
    提供列表大小已更改的次数,此值在每次
    next()
    调用中使用,以检查函数中的任何修改
    checkForComodification()

    如果在迭代对象中
    mapIterator.next()
    modCount
    中发现更改,则它将抛出
    ConcurrentModificationException

    要避免这种情况,请遵循以下几点:

  • 您可以将列表转换为数组,然后在数组上迭代。这种方法适用于中小型列表,但如果列表很大,则会对性能产生很大影响

  • 通过将列表放入同步块,可以在迭代时锁定列表。不建议使用这种方法,因为它将停止多线程的好处

  • 如果您使用的是JDK1.5或更高版本,则可以使用ConcurrentHashMap和CopyOnWriteArrayList类。这是推荐的方法

  • 在这种情况下,该行 mapIterator.next() 抛出ConcurrentModificationException

    这背后的原因是:
    有一个
    int
    变量
    modCount
    提供列表大小已更改的次数,此值在每次
    next()
    调用中使用,以检查函数中的任何修改
    checkForComodification()

    如果在迭代对象中
    mapIterator.next()
    modCount
    中发现更改,则它将抛出
    ConcurrentModificationException

    要避免这种情况,请遵循以下几点:

  • 您可以将列表转换为数组,然后在数组上迭代。这种方法适用于中小型列表,但如果列表很大,则会对性能产生很大影响

  • 通过将列表放入同步块,可以在迭代时锁定列表。不建议使用这种方法,因为它将停止多线程的好处

  • 如果您使用的是JDK1.5或更高版本,则可以使用ConcurrentHashMap和CopyOnWriteArrayList类。这是推荐的方法


  • 是否有多个线程同时访问映射?作为旁白(这可能不会自行修复CME),您也可以执行
    此操作。attributeMap.keySet().removeIf(k->k.matches(pattern))
    @VictorGalvez然后您需要以某种方式确保以独占方式访问映射,无论它在哪里读取或写入。是的,有多个线程访问,removeIf()只与Java8兼容。它很简单。我们阻止使用synchronized-keyword同时访问映射。是否有多个线程同时访问映射?作为一种旁白(这可能不会自行修复CME),您还可以执行
    this.attributeMap.keySet().removeIf(k->k.matches(pattern))
    @VictorGalvez然后您需要以某种方式确保对地图的独占访问,无论它在哪里读取或写入。是的,有多个线程访问,并且removeIf()仅与Java 8兼容。它很简单。我们使用synchronized关键字阻止对地图的并发访问。@MihaiChelaru,谢谢您的帮助