错误的方法:
public void filter(){ //List<String> list = new List<>(); List<String> list = new ArrayList<String>(Arrays.asList("111","222...","3333","444...","5555...")); for (int i=0;i<list.size();i++){ String s = list.get(i); System.out.println("ss"+i+"out"+s); if (s.endsWith("...")){ list.remove(i); } }
}
输出结果为:
这种方法或许看着感觉没什么问题,但上面这种方式会抛出java.lang.IndexOutOfBoundsException
异常。这种方式的问题在于,删除某个元素后,list的大小发生了变化,而你的索引也在变化。假设被遍历list中共有10个元素,当删除了第3个元素后,第4个元素就变成了第3个元素了,第5个就变成了第4个了,但是程序下一步循环到的索引是第4个,这时候取到的就是原本的第5个元素了。这样当迭代到最后一个的时候就会抛异常。因此,这种方式可以用在删除特定的一个元素时使用,但不适合循环删除多个元素时使用。
改进方法: https://blog.csdn.net/GarfieldEr007/article/details/80260818
for(int i=0,len=list.size();i< len;i++){ if(list.get(i).equals("del")){ list.remove(i); --len;//减少一个 //此时要注意,因为list会动态变化不像数组会占位,所以当前索引应该后退一位 --i; } }
个人觉得这时候使用迭代器,就比较方便了很多
public void filter(){ //List<String> list = new List<>(); List<String> list = new ArrayList<String>(Arrays.asList("111","222...","3333","444...","5555...")); Iterator<String> it = list.iterator(); while(it.hasNext()){ String x = it.next(); System.out.println("out"+x); if(x.endsWith("...")){ it.remove(); } } System.out.println(list.toString()); System.out.println("================="); }
输出结果为
迭代器iterator的remove()方法不仅会删除元素,还会维护一个标志,用来记录目前是不是可删除状态。例如,你不能连续两次调用它的remove()方法,调用之前至少有一次next()方法的调用。但是要注意的是:list.remove()只是删除元素,可是不会改变原有元素的位置。比如有 0 1 2 3 4 5这六个元素,我删除掉3这个元素,则4还是处于第四个位置,不会跳到第三个位置。