目录
我们说不能在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 中元素的下标,可能存 在漏删的情况。
除了直接使用普通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 的值。那么就不会再抛出异常了。
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);
如果,我们非常确定在一个集合中,某个即将删除的元素只包含一个的话, 比如对 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 > 集合类
在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 删除。