前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >如何在遍历的同时删除ArrayList 中的元素

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

原创
作者头像
小马哥学JAVA
发布2022-11-21 11:48:39
发布2022-11-21 11:48:39
3.8K0
举报
文章被收录于专栏:JAVA开发专栏JAVA开发专栏

目录

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 包下的容器都是安全失败,可以在多线程下并发使用,并发修改。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、直接使用普通for 循环进行操作
  • 2、直接使用Iterator 进行操作
  • 3、使用Java 8 中提供的filter 过滤
  • 4、使用增强for 循环其实也可以
  • 5、直接使用fail-safe 的集合类
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档