问题描述
1. for each中用remove删除元素
使用for each遍历容器(如List)并执行remove操作时,运行时报错。
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
System.out.println(list);
for(int i : list){
if (i == 1){
list.remove(i);
}
}
System.out.println(list);
}
2. 迭代器用remove删除元素
使用迭代器遍历容器(如List)并执行remove操作时,运行结果与预期不符。
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list);
Iterator<Integer> iter = list.iterator();
while (iter.hasNext()){
Integer i = iter.next();
if(i > 0){
list.remove(i);
}
}
System.out.println(list);
}
虽然会和上面那个报错相同,这是由于快速失败(fail-fast)策略导致的,不妨分析若强制运行下去,会发现最终列表是[2]而不是[]。
原因分析
- 调用list.remove()方法导致modCount和expectedModCount的值不一致
详细过程有很多博客已经讲的很清楚了,不再赘述。
- MyIterator内部维护着一个index变量用于标记正在遍历到的下标,list中删除元素后,下标变化,故遍历出错。原理同下:
解决方案
- 不要用增强的for循环,而老老实实按照下标遍历
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
System.out.println(list);
int size = list.size(); // 防止删除同时list在同时改变大小
for(int i = 0; i < size; i++){
if (list.get(i) == 1){
list.remove(i);
}
}
System.out.println(list);
}
- 不要用list.remove,而用迭代器的iter.remove
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list);
Iterator<Integer> iter = list.iterator();
while (iter.hasNext()){
Integer i = iter.next();
if(i > 0){
iter.remove();
}
}
System.out.println(list);
}
总结
尽可能用迭代器来遍历,并使用迭代器的remove方法来删除元素。