直接上代码:
import java.util.*;
/**
* @author :lyy
* @date : 04-04-12:52
*
* 测试集合遍历过程中增删改元素的影响
*/
public class TestCollectionForeach {
static String[] ss={"aaa","bbb","ccc"};
static ArrayList<String> strs= new ArrayList<>(Arrays.asList(ss));
// 测试Iterator遍历中的增删改
public static void testIterator(){
Iterator<String> ite=strs.iterator();
// 删除aaa
while(ite.hasNext()){
String item=ite.next();
if("aaa".equals(item))
strs.remove("aaa");//注意这里是strs的remove而不是ite.remove
}
// 增加ddd
while(ite.hasNext()){
String item=ite.next();
if("aaa".equals(item))
strs.add("ddd");//注意这里是strs的remove而不是ite.remove
}
// 修改aaa为ddd,不报错
while(ite.hasNext()){
String item=ite.next();
if("aaa".equals(item))
strs.set(0,"ddd");//注意这里是strs的remove而不是ite.remove
}
System.out.println(strs);
}
// 测试for遍历的增删改
public static void testFor(){
// 删除
for(String item:strs){
if("aaa".equals(item))
strs.remove("aaa");
}
// 增加
for(String item:strs){
if("aaa".equals(item))
strs.add("ddd");
}
// 改
for(String item:strs){
if("aaa".equals(item))
strs.set(0,"ddd");
}
System.out.println(strs);
}
// 测试foreach遍历的增删改
public static void testForeach(){
// 删除
strs.forEach(s->{
if("aaa".equals(s))
strs.remove("aaa");
});
// 增加
strs.forEach(s->{
if("aaa".equals(s))
strs.add("ddd");
});
// 修改
strs.forEach(s->{
if("aaa".equals(s))
strs.set(0,"ddd");
});
System.out.println(strs);
}
// 测试使用Iterator的remove来删除元素
public static void testIteratorForRemove(){
Iterator<String> ite=strs.iterator();
while(ite.hasNext()){
String item=ite.next();
if("aaa".equals(item))
ite.remove();
}
System.out.println(strs);
}
// 测试for遍历从后往前增删
public static void testForFromTail(){
int n=strs.size();
// 删除
for(int i=n-1;i>=0;--i){
if("aaa".equals(strs.get(i))){
strs.remove("aaa");
}
}
// 增加
for(int i=n-1;i>=0;--i){
if("aaa".equals(strs.get(i))){
strs.add("ddd");
}
}
System.out.println(strs);
}
public static void main(String[] args) {
// 测试Iterator遍历中的增删改:增删报错,改不报错
testIterator();
// 测试for遍历的增删改:增删报错,改不报错
testFor();
// 测试foreach遍历的增删改:增删报错,改不报错
testForeach();
// 测试解决方案
// 测试使用Iterator的remove来删除元素:成功,没法测试修改和增加,因为迭代器只支持remove
testIteratorForRemove();
// 测试使用for循环从后往前增删:成功
testForFromTail();
}
}
结论就是:
在迭代器遍历、for遍历、foreach遍历时,进行增删操作都会失败报错,而修改操作则成功。
解决方法:使用迭代器的删除方法,或者从后往前for循环。
其实for循环的报错原理很好理解,不只是从后往前遍历,在正常遍历时人工的修改for循环中的i的值,使其不越界就可以。因为每次strs.size()是取的实时的值,如果事先用n得到,那n的值是旧值,不是实时变化的。