如何在遍历的同时删除ArrayList 中的元素

简介: 如何在遍历的同时删除ArrayList 中的元素

目录


1、直接使用普通for 循环进行操作

2、直接使用Iterator 进行操作

3、使用Java 8 中提供的filter 过滤

4、使用增强for 循环其实也可以

5、直接使用fail-safe 的集合类


1、直接使用普通for 循环进行操作

我们说不能在foreach 中进行,但是使用普通的for 循环还是可以的,因为普通for

循环并没有用到Iterator 的遍历,所以压根就没有进行fail-fast 的检验。

List<String> userNames = new ArrayList<String>() {{

add("Hollis");

add("hollis");

add("HollisChuang");

add("H");

}};

for (int i = 0; i < 1; i++) {

if (userNames.get(i).equals("Hollis")) {

userNames.remove(i);

}

}

System.out.println(userNames);

这种方案其实存在一个问题,那就是remove 操作会改变List 中元素的下标,可能存

在漏删的情况。

2、直接使用Iterator 进行操作

除了直接使用普通for 循环以外,我们还可以直接使用Iterator 提供的remove 方法。

List<String> userNames = new ArrayList<String>() {{

add("Hollis");

add("hollis");

add("HollisChuang");

add("H");

}};

Iterator iterator = userNames.iterator();

while (iterator.hasNext()) {

if (iterator.next().equals("Hollis")) {

iterator.remove();

}

}

System.out.println(userNames);

集合类< 194

如果直接使用I t e r a t o r 提供的r e m o v e 方法, 那么就可以修改到

expectedModCount 的值。那么就不会再抛出异常了。

3、使用Java 8 中提供的filter 过滤

Java 8 中可以把集合转换成流,对于流有一种filter 操作, 可以对原始Stream 进

行某项测试,通过测试的元素被留下来生成一个新Stream。

List<String> userNames = new ArrayList<String>() {{

add("Hollis");

add("hollis");

add("HollisChuang");

add("H");

}};

userNames = userNames.stream().filter(userName -> !userName.equals("Hol

lis")).collect(Collectors.toList());

System.out.println(userNames);

4、使用增强for 循环其实也可以

如果,我们非常确定在一个集合中,某个即将删除的元素只包含一个的话, 比如对

Set 进行操作,那么其实也是可以使用增强for 循环的,只要在删除之后,立刻结束循环体,

不要再继续进行遍历就可以了,也就是说不让代码执行到下一次的next 方法。

List<String> userNames = new ArrayList<String>() {{

add("Hollis");

add("hollis");

add("HollisChuang");

add("H");

}};

for (String userName : userNames) {

if (userName.equals("Hollis")) {

userNames.remove(userName);

break;

}

}

System.out.println(userNames);

195 > 集合类

5、直接使用fail-safe 的集合类

在Java 中,除了一些普通的集合类以外,还有一些采用了fail-safe 机制的集合类。

这样的集合容器在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝

的集合上进行遍历。

由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能

被迭代器检测到,所以不会触发ConcurrentModificationException。

ConcurrentLinkedDeque<String> userNames = new ConcurrentLinkedDeque<String>

() {{

add("Hollis");

add("hollis");

add("HollisChuang");

add("H");

}};

for (String userName : userNames) {

if (userName.equals("Hollis")) {

userNames.remove();

}

}

基于拷贝内容的优点是避免了ConcurrentModificationException,但同样地,迭代

器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍

历期间原集合发生的修改迭代器是不知道的。

java.util.concurrent 包下的容器都是安全失败,可以在多线程下并发使用,并发修改。

相关文章
|
安全
ArrayList中remove()方法删除元素之后下标重定位的问题
ArrayList中remove()方法删除元素之后下标重定位的问题
List中移除指定元素
List中移除指定元素
96 0
遍历 ArrayList和遍历 Map的几种方式
遍历 ArrayList和遍历 Map的几种方式
66 0
|
Java
ArrayList与LinkedList遍历方式对比及List遍历技巧
ArrayList与LinkedList遍历方式对比及List遍历技巧
85 0
|
Java
ArrayList与LinkedList的遍历删除元素方法
ArrayList与LinkedList的遍历删除元素方法
306 0
逆序遍历List集合
逆序遍历List集合
65 0
|
自然语言处理 Java
遍历list时删除元素发生了什么?
遍历list时删除元素发生了什么?
116 0
批量遍历 list 中的元素
批量遍历 list 中的元素
106 0
批量遍历 list 中的元素
76. List如何一边遍历,一边删除
76. List如何一边遍历,一边删除
140 0
76. List如何一边遍历,一边删除
|
安全 Java
遍历List移除元素的若干种方法
遍历List移除元素的若干种方法
353 0