Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从ArrayList中删除元素时的ConcurrentModificationException_Java_Collections - Fatal编程技术网

Java 从ArrayList中删除元素时的ConcurrentModificationException

Java 从ArrayList中删除元素时的ConcurrentModificationException,java,collections,Java,Collections,当我运行以下代码时,Java正在抛出ConcurrentModificationException。知道为什么吗 ArrayList<String> list1 = new ArrayList<String>(); list1.add("Hello"); list1.add("World"); list1.add("Good Evening"); for (String s : list1){ list1.remove(2); System.ou

当我运行以下代码时,Java正在抛出
ConcurrentModificationException
。知道为什么吗

ArrayList<String> list1 = new ArrayList<String>();
list1.add("Hello");
list1.add("World");
list1.add("Good Evening");

for (String s : list1){
        list1.remove(2);
    System.out.println(s);
}
ArrayList list1=新的ArrayList();
列表1.添加(“你好”);
列表1.添加(“世界”);
列表1.添加(“晚上好”);
for(字符串s:list1){
清单1.移除(2);
系统输出打印项次;
}

如果你看一下的文档,你会发现

此异常可能由检测到并发的方法引发 当不允许修改对象时,对对象进行修改

例如,通常不允许一个线程修改 当另一个线程在其上迭代时创建集合

请注意,此异常并不总是表示对象具有 被另一个线程同时修改。如果是单线程 发出一系列违反 对象时,该对象可能会引发此异常例如,如果 线程在集合上迭代时直接修改集合 集合,迭代器将抛出 异常

关于这个异常的重要一点是,我们不能保证它总是按照文档中的说明抛出

请注意,通常不能保证快速失效行为 说起来,在有人在场的情况下,不可能做出任何硬性保证 未同步的并发修改快速失败操作抛出
ConcurrentModificationException
尽最大努力

也来自文件

此类的
迭代器
列表迭代器
方法是快速失败的:如果列表在任何时候进行了结构修改 创建迭代器后的时间,以任何方式,除了通过 迭代器自己的remove或add方法,迭代器将抛出
ConcurrentModificationException

(强调矿山)

所以,当通过增强的for循环对集合进行迭代时,您不能操作集合的内容(在您的案例列表中),因为您并没有通过迭代器对每个正在内部使用的集合进行操作

要解决它,只需使用自己的
迭代器
,并在循环中使用它。要从集合中删除元素,请使用与本例类似的
remove

Iterator<String> it = list1.iterator();
int i=0;
while(it.hasNext()){
    String s = it.next();
    i++;
    if (i==2){
        it.remove();
        System.out.println("removed: "+ s);
    }
}
Iterator it=list1.Iterator();
int i=0;
while(it.hasNext()){
字符串s=it.next();
i++;
如果(i==2){
it.remove();
System.out.println(“删除:+s”);
}
}

在迭代时,不能使用
ArrayList
remove()
方法删除项目。如果要在迭代时删除该项,请使用
迭代器

但是您正在根据索引删除一个项目,然后只需在循环外的行下方移动即可解决您的问题

 list1.remove(2);
你可以阅读的表格

此异常可能由检测到并发的方法引发 当不允许修改对象时,对对象进行修改。 例如,通常不允许一个螺纹进行修改 当另一个线程在集合上迭代时,该集合将被删除。一般来说 在这些情况下,迭代的结果是未定义的。 一些迭代器实现(包括所有通用 JRE提供的目的集合实现可以选择 如果检测到此行为,则引发此异常。迭代器 这被称为fail fast迭代器,因为它们的失败速度很快,速度也很快 干净地说,更确切地说,是冒着任意的、不确定的行为的风险 未来不确定的时间

此外,假设您可以在每次迭代中删除项2。最终将出现索引越界异常:

  • 在第一次迭代中,删除项目2(
    “Good Night”
    ),列表大小变为1(项目0
    “hello”
    和项目1
    “World”
  • 在下一次迭代中,您将删除列表中实际上不存在的项#2。您的列表确实大小为2,但计数器从0开始,所以您最终删除了不存在的内容:这是一个非确定性行为的示例

在修改基础列表后,您不能在列表上进行迭代。如果您这样做,它将为您提供
ConcurrentModificationException

要解决此问题,请使用
java.util.ListIterator
对列表进行迭代

    ListIterator<String> it = list1.listIterator();
    for (String s : list1) {
        if (it.hasNext()) {
            String item = it.next();
            System.out.println(item);
        }
        }
ListIterator it=list1.ListIterator();
for(字符串s:list1){
if(it.hasNext()){
String item=it.next();
系统输出打印项次(项);
}
}

我同意,它与迭代器一起工作。但是,当我在同一个循环中添加if语句时,为什么不给我一个错误呢。这是代码。对于(字符串s:list1){if(s.equals(“World”){list1.remove(1);}}请尝试使用(字符串s:list1){if(s.equals(“Hello”){list1.remove(1);}
您不能删除尚未处理的项目,也可以说其索引大于for each循环的当前运行索引。我不确定,但这是一个好问题。让我试着找出确切的原因。@user3520698,正如我在回答中指出的,抛出此异常无法保证。快速失败的操作会尽最大努力抛出ConcurrentModificationException。其中一个原因可能是通过线程缓存修改计数器(如果您查看
ArrayList
类中的
modCount
,您将不会看到
volatile
修饰符,这可能会阻止缓存该值)。查看输出,其所有项都显示为“已删除”。Erick也给出了类似的解释(虽然格式较短:)[是的,现在我搜索了
ArrayList
ConcurrentModificationException
之后,我发现了许多简短的问题