最近Java编写过程中需要从一组ArrayList集合里面删除某些指定的元素,但是用Iterator按照常规做后遇到了一个java.util.ConcurrentModificationException异常,查询资料知这不是逻辑问题,这时由于Java自身的机制造成的,很不容易引起注意;
首先介绍 Iterator的工作机制:
Iterator是工作在一个独立的线程中,并且拥有一个 mutex锁,Iterator在工作的时候,不允许被迭代的对象改变。Iterator被创建的时候,建立了一个内存索引表(单链表),这个索引表指向原来的对象,当原来的对象数量改变的时候,这个索引表的内容没有同步改变,所以当索引指针往下移动的时候,便找不到要迭代的对象,于是产生错误。List、Set等是动态的,可变对象数量的数据结构,但是Iterator则是单向不可变,只能顺序读取,不能逆序操作的数据结构,当 Iterator指向的原始数据发生变化时,Iterator自己就迷失了方向。因而产生了上述异常;
可以采取如下方法解答:
首先建立一个新的临时集合,然后用Iterator迭代器去遍历数据,将需要删除的数据项添加到新建的临时集合里面,最后调用集合的removeAll(Collection con)方法就可以了。
以下是一个示例:
public class Test {
public static void main(String[] args) {
boolean flag = false;
User user1 = new User();
user1.setId(1);
user1.setName("shangsan");
User user2 = new User();
user2.setId(2);
user2.setName("lisi");
Set userSet = new HashSet();
userSet.add(user1);
userSet.add(user2);
List delList = new ArrayList();
for (Iterator it = userSet.iterator(); it.hasNext();) {
User user = (User) it.next();
if (user.getId() == 1) {
delList.add(user);
}
if (user.getId() == 2) {
user.setName("zhangsan");
}
}
userSet.removeAll(delList);
for(Iterator it = userSet.iterator(); it.hasNext(); ) {
User user = (User) it.next();
System.out.println(user.getId() + "=>" + user.getName());
}
}
}