ArrayList应该是在我们开发中最常用的集合,有时候我们业务需求,需要在循环中删除一个或者多个元素,我们怎样去在循环中删除ArrayList中的元素呢?
错误案例一:
public class ArrayListDeleteDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
for (String str : list) {
list.remove(str);
}
System.out.println(list);
}
}
运行结果:
这里抛了ConcurrentModificationException, ConcurrentModificationException是基于java集合中的快速失败(fail-fast)机制产生的,在使用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了增删改,就会抛出该异常。快速失败机制使得java的集合类不能在多线程下并发修改,也不能在迭代过程中被修改。
错误案例二:
public class ArrayListDeleteDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
for (int i = 0; i < list.size(); i++) {
list.remove(i);
}
System.out.println(list);
}
}
这个案例乍一看,好像没啥问题,那我们看看运行结果:
通过运行结果可以看出,跟我们预期的不一样,没有删干净,是因为循环中删除会导致被删元素后续元素的索引发生变化,后续元素都会往前挪一位,所以会出现了这样的结果。
正确案例一:
public class ArrayListDeleteDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
for (int i = list.size() -1 ; i >=0; i--) {
list.remove(i);
}
//或者以下方式也能达到同样的效果
//for (int i = 0; i < list.size(); i++) {
// list.remove(i);
// i--;
//}
System.out.println(list);
}
}
上面的错误案例二是正序删的,会有索引挪位的问题,那我倒过来删不就可以解决嘛,每次删除最后那一个,就不会有索引挪位的问题了。
运行结果:
根据运行结果可以看出,正确的把元素删干净了。
正确案例二:
public class ArrayListDeleteDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
//如果不加这句代码,会有什么后果,大家想想
iterator.next();
iterator.remove();
}
System.out.println(list);
}
}
这里我们使用迭代器来循环删除,也是能正确删除数组里的元素。
运行结果:
正确案例三:
public class ArrayListDeleteDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
List<String> delList = new ArrayList<>();
for (String str: list){
if(str.equals("a") || str.equals("b")){
delList.add(str);
}
}
list.removeAll(delList);
System.out.println(list);
}
}
这也是我们在项目开发中一种比较常用的删除方法,在循环里不删,记录下来需要被删的元素,待循环结束后再去统一删除。
运行结果:
总结:
本文给大家分享了一下循环删除的使用姿势,特别是正确案例二和正确案例三我比较推荐大家使用,但上述的几种方式中,都无法保证多线程安全,如果大家的业务需求是对线程安全有要求,就需要去加锁或者换线程安全的list集合。