关于list:我要在for循环List中删除元素

28次阅读

共计 1427 个字符,预计需要花费 4 分钟才能阅读完成。

前言:

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 后下一次遍历的时候才会报错,报异样的办法是 j ava.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);
    }}

正文完
 0