if("2".equals(item)) 替换成if("1".equals(item))执行结果不同
2的时候会抛快速失败异常,1的时候没有异常
if("2".equals(item)) 替换成if("1".equals(item))执行结果不同
2的时候会抛快速失败异常,1的时候没有异常
记住 , list的remove操作,不要直接操作,转换成Iterator
再进行操作
List<String> list = new ArrayList<>(16);
list.add("1");
list.add("2");
for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
if (iter.next().equals("2")) {
iter.remove();
}
}
4 回答1.5k 阅读✓ 已解决
4 回答1.3k 阅读✓ 已解决
1 回答2.6k 阅读✓ 已解决
3 回答2k 阅读
2 回答781 阅读✓ 已解决
2 回答1.7k 阅读
2 回答1.3k 阅读
其实呢,结论就是仅仅是巧合而已。。。对,就是只是巧合,这跟快速失败关系不大。当然最终报错是快速失败,但是导致一个报错一个不报错,跟快速失败实现关系不大
题主的给的代码编译后就是如下样子

调用顺序是
ArrayList.iterator()
,这里迭代器类是内部私有类ArrayList.Itr
var2.hasNext()
,也就是ArrayList.Itr.hasNext()
var2.next()
,也就是ArrayList.Itr.next()
然后
debug
这几个方法就可以简单看明白,假设现在是"2".equals(item)
的情况,也就是报错的情况第一个方法
iterator()
自不用说,主要是后两个方法在

ArrayList.Itr.hasNext()
的实现,主要是判断当前循环下标cursor
和ArrayList
的大小size
来决定是否还要循环的第一次进入
hasNext()
方法时,cursor
为0,size
为2,两不相等,所以循环继续在

ArrayList.Itr.next()
的第一步就有了快速失败检查checkForComodification()
,这自不用说,没问题然后判断
"2".equals(item)
没进入,再次走入hasNext()
方法,cursor
为1,size
为2,两不相等,所以循环继续这一次执行完
next()
方法后,判断"2".equals(item)
进入了,导致size
变为1第三次走入
hasNext()
方法,cursor
为2,size
为1,本来已经循环两次,要停止了,由于hasNext()
判断模式+size
变化,所以循环继续,这一次当然最后就是快速失败了。所以模仿上面的逻辑走向,判断条件变为
"1".equals(item)
时为啥不会报错,就是因为第一次进入循环,判断条件"1".equals(item)
成立导致size
变为1,第二次进入hasNext()
方法时,此时恰好cursor
为1,size
也为1,两个相等,所以循环就停止了,也不会进入next()
方法,也就不会报快速失败的错了。这也是为啥呼吸 ༽提到要直接使用迭代器
Iterator
来操作,因为for
循环的语法,最终会转换成Iterator
的模式但是你删除使用的方法却是

ArrayList
的remove
,而不是Iterator
的remove
因此

"2".equals(item)
时会导致快速失败,而Iterator
的remove
是有对快速失败的变量expectedModCount
有做修正的,因此不会报错