有学妹问我,集合迭代遍历时删除时会抛出ConcurrentModificationException异常导致遍历失败,今天就教她操做操做
ail-fast和fail-safe的区别:
fail-safe允许在遍历的过程中对容器中的数据进行修改,而fail-fast则不允许。
fail-fast ( 快速失败 )
fail-fast:直接在容器上进行遍历,在遍历过程中,一旦发现容器中的数据被修改了,会立刻抛出ConcurrentModificationException异常导致遍历失败。java.util包下的集合类都是快速失败机制的, 常见的的使用fail-fast方式遍历的容器有HashMap和ArrayList等。
在使用迭代器遍历一个集合对象时,比如增强for,如果遍历过程中对集合对象的内容进行了修改(增删改),会抛出ConcurrentModificationException 异常.
fail-fast的出现场景
在我们常见的java集合中就可能出现fail-fast机制,比如ArrayList,HashMap。在多线程和单线程环境下都有可能出现快速失败。
1、单线程环境下的fail-fast:
ArrayList发生fail-fast例子:
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0 ; i < 10 ; i++ ) {
list.add(i + "");
}
Iterator<String> iterator = list.iterator();
int i = 0 ;
while(iterator.hasNext()) {
if (i == 3) {
list.remove(3);
}
System.out.println(iterator.next());
i ++;
}
}
该段代码定义了一个Arraylist集合,并使用迭代器遍历,在遍历过程中,刻意在某一步迭代中remove一个元素,这个时候,就会发生fail-fast。
HashMap发生fail-fast:
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
for (int i = 0 ; i < 10 ; i ++ ) {
map.put(i+"", i+"");
}
Iterator<Entry<String, String>> it = map.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
if (i == 3) {
map.remove(3+"");
}
Entry<String, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
i++;
}
}
该段代码定义了一个hashmap对象并存放了10个键值对,在迭代遍历过程中,使用map的remove方法移除了一个元素,导致抛出了ConcurrentModificationException异常:
2、多线程环境下:
public class FailFastTest {
public static List<String> list = new ArrayList&