快速失败是当迭代器遍历集合的时候,如果集合的结构发生了改变(使用集合的添加或删除,迭代器的添加和删除不会报异常),迭代器就会抛出ConcurrentModificationException异常。
for (int i = 0; i < 3; i++) {
mStringList.add(String.valueOf(i));
Log.d(TAG, "add" + i);
}
Iterator<String> iterable = mStringList.listIterator();
while (iterable.hasNext()) {
String str = iterable.next();
if (str.equals("1")) {
// ConcurrentModificationException 异常
mStringList.remove(str);
// 不会报异常
iterable.remove();
}
}
为什么会报这个异常呢?查看ArrayList的源码就很清晰了。在创建迭代器的时候,迭代器会使用一个变量expectedModCount来保存列表的modCount。这个modCount是什么呢?modCount其实就是这个列表在结构上被修改的次数 。以后在使用迭代器的next,previous等方法的时候,就会根据expectedModCount是否等于modCount来判断列表的结构是否已经发生了改变。如果不相等,就抛出ConcurrentModificationException异常。
需要注意的是,forEach遍历的使用其实迭代器的方法,它也会去判断expectedModCount是否等于modCount来判断列表的结构是否已经发生了改变来抛出异常。
查看ArrayList集合官方的解释,快速失败的为了应对并发的修改(多线程场景),迭代器会快速干净的失败而不是冒着不确定的风险。