Java 许多集合都是非线程安全的,如果对它们进行并发操作会引发 fail - fast 机制,抛出 ConcurrentModificationException 异常。
我们先来看看这个异常吧。
源码如下:
public class ConcurrentModificationException extends RuntimeException {
private static final long serialVersionUID = -3666751008965953603L;
public ConcurrentModificationException() {
}
public ConcurrentModificationException(String message) {
super(message);
}
public ConcurrentModificationException(Throwable cause) {
super(cause);
}
public ConcurrentModificationException(String message, Throwable cause) {
super(message, cause);
}
}
源码似乎没什么特别之处。
我们还是直接引入一个例子吧:
假设我们要判断集合里面有没有 "Jerry" 这个元素,如果有,就往集合里添加一个 "Sad" 元素。代码如下:
import java.util.ArrayList;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<String>();
// 创建并添加元素
array.add("hello");
array.add("Jerry");
array.add("java");
Iterator it = array.iterator();
while (it.hasNext()) {
String s = (String) it.next();
if ("Jerry".equals(s)) {
array.add("Sad");
}
}
}
}
上面代码会不出意料地抛出 ConcurrentModificationException 异常。
1. 异常解释
ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
产生的原因:
迭代器是依赖于集合而存在的,在条件判断成功之后,在集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个叫并发修改异常。
简单描述就是:迭代器遍历元素的时候,是不能修改集合的。
如何解决呢?
先用迭代器迭代元素,再用迭代器修改元素;
遍历集合查找元素,然后通过集合修改元素(普通 for)。
2. 下面用两种方法解决这个异常
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<String>();
// 创建并添加元素
array.add("hello");
array.add("Jerry");
array.add("java");
// 方式1:先用迭代器迭代元素,再用迭代器修改元素.
// 而Iterator迭代器却没有添加功能,所以我们使用其子接口ListIterator
ListIterator lit = array.listIterator();
while (lit.hasNext()) {
String s = (String) lit.next();
if ("Jerry".equals(s)) {
lit.add("Sad");
}
}
System.out.println("list1:" + array);
// 方式2:遍历集合查找元素,遍历集合修改元素(普通 for)。
for (int x = 0; x < array.size(); x++) {
String s = (String) array.get(x);
if ("Jerry".equals(s)) {
array.add("Sad");
}
}
System.out.println("list2:" + array);
// 增强 for 循环不能解决问题。
// 增强 for 循环写的话会报同样的错误,因为它本身就是用来替代迭代器的。
/*for (String s : array) {
if ("world".equals(s)) {
array.add("javaee");
}
}
System.out.println("list3:" + array);*/
}
}