JAVA中循环遍历list有三种方式for循环、增强for循环(也就是常说的foreach循环)、iterator遍历。
1、for循环遍历list
@Test
public void test1(){
ArrayList list = new ArrayList();
list.add("1");
list.add("2");
list.add("2");
list.add("3");
for (int i =0;i<list.size();i++) {
if("2".equals(list.get(i))){
list.remove(list.get(i));
}
}
System.out.println("for循环删除:"+list.toString());
}
输出结果:
for循环删除:[1, 2, 3]
这种方式的问题在于,删除某个元素后,list的大小发生了变化,而你的索引也在变化,所以会导致你在遍历的时候漏掉某些元素。比如当你删除第1个元素后,继续根据索引访问第2个元素时,因为删除的关系后面的元素都往前移动了一位,所以实际访问的是第3个元素。因此,这种方式可以用在删除特定的一个元素时使用,但不适合循环删除多个元素时使用。
2、增强for循环
@Test
public void test2(){
ArrayList list = new ArrayList();
list.add("1");
list.add("2");
list.add("2");
list.add("3");
for (Object o : list) {
if("2".equals(o)){
list.remove(o);
}
}
System.out.println("增强for循环删除:"+list.toString());
}
输出结果:
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at cn.ml.test.ListTest.test2(ListTest.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
...
这种方式的问题在于,删除元素后继续循环会报错误信息ConcurrentModificationException,因为元素在使用的时候发生了并发的修改,导致异常抛出。但是删除完毕马上使用break跳出,则不会触发报错。
3、iterator遍历
@Test
public void test3(){
ArrayList list = new ArrayList();
list.add("1");
list.add("2");
list.add("2");
list.add("3");
Iterator it = list.iterator();
while (it.hasNext()) {
Object o = it.next();
if ("2".equals(o)) {
it.remove();
}
}
System.out.println("迭代器删除:"+list.toString());
}
输出结果:
迭代器删除:[1, 3]
这种方式可以正常的循环及删除。但要注意的是,使用iterator的remove方法,如果用list的remove方法同样会报上面提到的ConcurrentModificationException错误。
总结:
-
(1)循环删除list中特定一个元素的,可以使用for循环、迭代器,但在使用中要注意上面分析的各个问题。
(2)循环删除list中多个元素的,应该使用迭代器iterator方式。