Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/325.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中的快速失败迭代器 公共类Alpha{ 公共静态void main(字符串[]args){ ArrayList al=新的ArrayList(); al.添加(“a”); al.添加(“b”); al.添加(“c”); al.添加(“d”); al.添加(“e”); 迭代器itr=al.listIterator(); while(itr.hasNext()){ al.remove(“d”);//在此行抛出一个并发修改 如果(itr.next()等于(“d”)){ //itr.remove(); al.remove(“d”);//此行没有错误 } } 系统输出打印项次(al); } }_Java_Iterator_Fail Fast - Fatal编程技术网

Java中的快速失败迭代器 公共类Alpha{ 公共静态void main(字符串[]args){ ArrayList al=新的ArrayList(); al.添加(“a”); al.添加(“b”); al.添加(“c”); al.添加(“d”); al.添加(“e”); 迭代器itr=al.listIterator(); while(itr.hasNext()){ al.remove(“d”);//在此行抛出一个并发修改 如果(itr.next()等于(“d”)){ //itr.remove(); al.remove(“d”);//此行没有错误 } } 系统输出打印项次(al); } }

Java中的快速失败迭代器 公共类Alpha{ 公共静态void main(字符串[]args){ ArrayList al=新的ArrayList(); al.添加(“a”); al.添加(“b”); al.添加(“c”); al.添加(“d”); al.添加(“e”); 迭代器itr=al.listIterator(); while(itr.hasNext()){ al.remove(“d”);//在此行抛出一个并发修改 如果(itr.next()等于(“d”)){ //itr.remove(); al.remove(“d”);//此行没有错误 } } 系统输出打印项次(al); } },java,iterator,fail-fast,Java,Iterator,Fail Fast,换句话说,如果“al.remove”(“d”)放在if构造内部,则不会引发ConcurrentModificationException,其中作为同一行代码,如果放在if-construct外部,则会引发异常。请解释一下!这是因为当您使用itr.next()获取下一个元素时,它将检查集合的大小是否已更改。此时如果(modCount!=expectedModCount)条件将变为true。而方法仅根据当前光标点返回true或false 如果您愿意,itr.next(),然后在列表上调用remove

换句话说,如果“al.remove”(“d”)放在if构造内部,则不会引发ConcurrentModificationException,其中作为同一行代码,如果放在if-construct外部,则会引发异常。请解释一下!

这是因为当您使用
itr.next()获取下一个元素时
,它将检查集合的大小是否已更改。此时
如果(modCount!=expectedModCount)
条件将变为true。而方法仅根据当前光标点返回true或false

如果您愿意,
itr.next()
,然后在列表上调用remove,那么它也会更新
expectedModCount
变量。请检查Arraylist迭代器的方法。

重复:


您无法在迭代中删除元素。

请参见如何实现
ArrayList
迭代器:

public class Alpha {

    public static void main(String[] args) {
        ArrayList<String> al = new ArrayList<String>();

        al.add("a");
        al.add("b");
        al.add("c");
        al.add("d");
        al.add("e");


        Iterator<String> itr = al.listIterator();
        while(itr.hasNext()){
            al.remove("d"); // Throws a Concurrent Modification @ this line
            if(itr.next().equals("d")){
                //itr.remove();
                al.remove("d"); // No error on this line
            }

        }
        System.out.println(al);

    }

}
public void remove(){
if(lastRet<0)
抛出新的非法状态异常();
checkForComodification();
试一试{
ArrayList.this.remove(lastRet);
游标=lastRet;
lastRet=-1;
expectedModCount=modCount;
}捕获(IndexOutOfBoundsException ex){
抛出新的ConcurrentModificationException();
}
}

因此,它检查并发修改,使用公共ArrayList remove方法删除元素,并增加列表修改的计数器,以便ConcurrentModificationException不会在下一次迭代中抛出。

这就像您正在修改其他人当前使用的文件(此处为ArrayList)(此处为迭代循环)

使用这几行代码。希望这会有所帮助。

我添加了一行(第13行)和一些注释行号(第18行、第19行和第21行)

现在,ConcurrentModificationException不是在第18行抛出的,而是在第19行抛出的。但是是的,它是由于第18行的执行而抛出的

另外,我相信您正在使用第18行和第21行的代码,一次一个,它们不会同时出现在您的代码中

import java.util.*;
公共类HelloWorld{
公共静态void main(字符串[]args){
ArrayList al=新的ArrayList();
al.添加(“a”);
al.添加(“b”);
al.添加(“c”);
al.添加(“d”);
al.添加(“e”);
al.add(“f”);//第13行
迭代器itr=al.listIterator();
while(itr.hasNext()){
al.删除(“d”);//第18行
如果(itr.next().equals(“d”){//第19行
//itr.remove();
al.删除(“d”);//第21行
}
}
系统输出打印项次(al);
}
}
让我们注释第13行。这基本上是你的代码,还有一些额外的注释

如果我们检查迭代器的实现,我们就会知道它在一开始就检查任何修改(从而抛出CoMo),然后它只返回元素

因此,如果我们不使用第18行的迭代器而从列表中删除元素,则会在下面的next()调用中检测到。但是如果在next()方法之后删除元素(在第21行;现在第18行已注释),则只会在后续的next()中检测到CoMo。在您的情况下,我们在打印“e”后用完了元素。。因此我们从未执行后续的next(),也没有得到异常


现在,如果我们取消对第13行的注释(它添加了一个新元素),那么我们将在第19行得到ConcurrentModificationException,即当next()时执行。这证明我们将得到CoMo异常,只是我们将在一次迭代后得到它。

正如@VimalBera在前面的回答中指出的那样:在调用
列表上的remove之前,必须使用
itr.next()
获取下一个元素

但是,我发现有一些替代方法更适合此用例。第一种方法是在删除元素时使用迭代器:

import java.util.*;

public class HelloWorld{

public static void main(String []args){
    ArrayList<String> al = new ArrayList<String>();

    al.add("a");
    al.add("b");
    al.add("c");
    al.add("d");
    al.add("e");
    al.add("f"); // line 13


    Iterator<String> itr = al.listIterator();
    while(itr.hasNext()){
        al.remove("d"); // line 18
        if(itr.next().equals("d")){  // line 19
            //itr.remove();
            al.remove("d"); // line 21
        }

    }
    System.out.println(al);
}
}
使用这种方法,您显然会获得新列表的额外开销,但相反,您可以将列表视为不可变的,这将在多线程环境中很好地工作

while(itr.hasNext()){

            if(itr.next().equals("d"))
            {
                //itr.remove();
                al.remove("d"); // No error on this line
            }

        }
        System.out.println(al);
import java.util.*;

public class HelloWorld{

public static void main(String []args){
    ArrayList<String> al = new ArrayList<String>();

    al.add("a");
    al.add("b");
    al.add("c");
    al.add("d");
    al.add("e");
    al.add("f"); // line 13


    Iterator<String> itr = al.listIterator();
    while(itr.hasNext()){
        al.remove("d"); // line 18
        if(itr.next().equals("d")){  // line 19
            //itr.remove();
            al.remove("d"); // line 21
        }

    }
    System.out.println(al);
}
}
public static void main(String[] args) {
    List<String> al = new ArrayList<>();
    al.add("a");
    al.add("b");
    al.add("c");
    al.add("d");
    al.add("e");

    for (Iterator<String> itr = al.listIterator(); itr.hasNext(); ) {
        String s = itr.next();
        if ("d".equals(s)) {
            itr.remove();
        }
    }
    System.out.println(al);
}
public static void main(String[] args) {
    List<String> al = Arrays.asList("a", "b", "c", "d", "e");
    List<String> filtered = al.stream()
            .filter(s -> !s.equals("d"))
            .collect(Collectors.toList());
    System.out.println(filtered);
}