我要在for循环List中删除元素

熵桥冰川
• 阅读 1250

前言:

for循环可以删除集合元素吗,往往我们得到的答案有时候就是不可以,安全起见,要迭代器,包括我在阿里的开发规范里也写了这么一句话, 不要在 foreach 循环里进行元素的 remove / add 操作。remove 元素请使用 iterator 方式,如果并发操作,需要对 iterator 对象加锁 

依然记得刚来第三天写个接口我就for循环内删除元素,当时很沙雕,恰好又被代码走查看到了,尴尬的我挖了个洞将for改成了迭代器方式遍历,这两天看个大佬的代码,他就是for循环并remove其中元素,我开心的以为发现了一个bug,嗯,再往下看不对,这代码妙啊,百度了一下,有了这篇文章 下面我们通过几个例子以及分析源码的方式来看看问题,nice

问题一

List<String> list = new ArrayList();
list.add("111");
list.add("222");
list.add("222");
list.add("333");
list.add("222");
list.add("555");
//list.stream().forEach(System.out::println);
for(int i = 0;i < list.size();i++){    
if(StrUtil.equals("222",list.get(i))){
        list.remove(i);  
  }}

我们先看下上面这个用例,这个结果是啥呢?是111 222 333 555,咦,明明等于222的移除了啊,怎么没移掉,而且还没报错,通常我们移除元素会报错呀,其实这种for方法在我们循环遍历的时候list.remove(i);会删除对应的元素不会报错,但是呢,删除的元素位置会空出来,后面的元素会往前移一位,这样如果有两个元素的位置是连续的话,那么后面这个元素是不会进行判断的,这样就不会符合我们的分析场景的,

我们按代码顺序翻一下,索引在范围内,则获取remove的元素,然后将list的元素大小减一,如果还存在,就进行元素的copy,从源数组的index+1位置开始要复制的数组元素的数量numMoved,到目标数组的指定位置,然后通过GC将最后一个位置内存回收,哦。原来是这样的,至于说的报错我们下面在分析

问题二

for (String ll : list) {    
 if(StrUtil.equals(ll,"333")){  
      list.remove(ll);   
 }}

如上代码,当我们使用foreach的时候我们需要remove的是一个对象,而不是for时的下标,这里会报错java.util.ConcurrentModificationException,这就是我们说的报错了,我先把结果说了吧,这里我们删除元素的话其实并不会报错,报错的是for循环哪里,在你remove后下一次遍历的时候才会报错,报异常的方法是java.util.ArrayList$Itr.checkForComodification,一看就是方法里的迭代器报错

  • 一个是删除后元素位置前挪了导致连续相等的元素判断不到
  • 一个是删除元素后改动的次数变得和期望变动的次数不一样了导致的这些异常信息
for(int i = list.size()-1;i>=0;i--){    
    if(StrUtil.equals("222",list.get(i))){        
        String remove = list.remove(i);   
        System.out.println("shanchu"+ remove);
    }}

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
JS中arr.forEach()如何跳出循环
示例我们都知道for循环里要跳出整个循环是使用break,但在数组中用forEach循环如要退出整个循环呢?使用break会报错,使用return也不能跳出循环。使用break将会报错:vararr使用return也不能跳出整个循环:vararr那么在用forEach()遍历数组时要如何才能跳出循环呢?经过查找资料后,我找到了两种方法可以实现跳出
Wesley13 Wesley13
3年前
java 数据结构(十二):Collections工具类的使用
Collections工具类1.作用:操作Collection和Map的工具类2.常用方法:reverse(List):反转List中元素的顺序shuffle(List):对List集合元素进行随机排序sort(List):根据元素的自然顺序对指定List集合元素升序排序sort(List,Comparator)
Wesley13 Wesley13
3年前
java List 数组删除元素
在java中,ArrayList是一个很常用的类,在编程中经常要对ArrayList进行增、删、改、查操作。之前在学校时一直认为删除操作是最简单的,现在才越发觉得自己愚蠢。只需要设置好预期条件的查询才是最简单的,删除涉及到存储空间的释放,以及数组的遍历等问题,在list的操作中相对还算小老哥呢。这两天在给小程序提供后台接口,因为设计的改变,需要
执键写春秋 执键写春秋
4年前
Java练习(三)——返回集合中的最大的和最小的元素
题目:在一个列表中存储以下元素:apple,grape,banana,pear,现要求将集合进行排序,返回集合中的最大的和最小的元素,并将排序后的结果打印在控制台上,要求的打印输出方法分别为默认toString输出、迭代器输出、for循环遍历输出和增强for循环输出。packagetest;importjava.util.;publicclassP
Stella981 Stella981
3年前
Python中的list详解
Python中内置的一种数据类型list,列表。list是一个有序集合,所谓有序集合就是可以通过Key或者Index进行访问(无序集合,集合的元素只能遍历,比如set)。list能随时随地进行增加和删除。python中list用\\进行表示。例如:\\\friends\'fanbinbin','libinbin','xijin
Wesley13 Wesley13
3年前
Java 删除List元素的正确方式
方式一:使用Iterator的remove()方法publicclassTest{publicstaticvoidmain(Stringargs){List<StringlistnewArrayList<();list.add("aa"
Wesley13 Wesley13
3年前
Java内功系列
面试官:你能简单介绍List和Set有什么区别吗?小憨:List是一个有序的集合,在内存是连续存储的,可以存储重复的元素,List查询快,增删慢;Set是一个无序的集合,在内存中不连续,不可以存储重复的元素,Set增删快,查询慢;面试官:那HashSet是如何保证元素不重复的?小憨:3分钟。。。
Wesley13 Wesley13
3年前
JAVA中循环删除list中元素的方法总结
印象中循环删除list中的元素使用for循环的方式是有问题的,但是可以使用增强的for循环,然后今天在使用时发现报错了,然后去科普了一下,再然后发现这是一个误区。下面就来讲一讲。。伸手党可直接跳至文末。看总结。。  JAVA中循环遍历list有三种方式for循环、增强for循环(也就是常说的foreach循环)、iterator遍历。1、for循环遍
Wesley13 Wesley13
3年前
Java删除List元素的方法
一、正序删正序删,如果只删除至多1个元素,那只需要在删除后使用break语句跳出循环即可,如果需要删除多个元素,若不注意控制当前列表的size和下一个元素的index,容易报_java.lang.IndexOutOfBoundsException_异常publicstaticvoidremove(List<Stringlis
Wesley13 Wesley13
3年前
Java_Learn
20180417集合类Collection如果是实现了list接口的集合类,具备的特点是有序,可重复;如果是实现了set接口的集合类,具备的特点是无序,不可重复;Collection中的方法 增加 删除查看  add("添加任意类型的元素到集合中"); addall("添加一个集合的元素到另外一个集合中") clear("
小万哥 小万哥
1年前
NumPy 数组迭代与合并详解
NumPy数组迭代NumPy数组迭代是访问和处理数组元素的重要方法。它允许您逐个或成组地遍历数组元素。基本迭代我们可以使用Python的基本for循环来迭代NumPy数组。一维数组迭代:pythonimportnumpyasnparrnp.array(1