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); } }
换句话说,如果“al.remove”(“d”)放在if构造内部,则不会引发ConcurrentModificationException,其中作为同一行代码,如果放在if-construct外部,则会引发异常。请解释一下!这是因为当您使用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
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);
}