在遍历List时,对List里的对象进行remove(),此操作会改变List的大小()

先看看代码:

1 for(ComType com : ComList){
2    if(!com.getName.contains("abc")){
3       CosList.remove(com);
4    }
5 }

通过这段代码,并没有过滤掉不包含“abc”的元素。经过测试分析得到结论是:在每一次remove()时,改变了CosList的大小(size),导致CosList遍历不完整。

空指针 空指针
发帖于 1年前
14回/5391阅

按票数排序  显示最新答案  共有14个答案 (最后回答: 1年前)

  • 1
  • liuex
    简化的for-each循环实际上只是一个语法糖,会被编译器转化成以下等价的代码:
    1 for( Iterator<ComType> iter = ComList.iterator(); iter.hasNext();){
    2     ComType com = iter.next();
    3     if ( !com.getName().contains("abc")){
    4         ComList.remove(com);
    5     }
    6 }

    也就是说,你在同时遍历和删除一个List,大多List实现是不允许这种操作的(某些List实现允许同时遍历和修改,例如CopyOnWriteArrayList),会抛并发修改异常。(具体可以参考ArrayList的源代码,ArrayList上面的ArrayList.iterator()操作会记录当前的修改次数modCount,remove/add操作会让修改次数自增,即modCount++,因此就能判断出来是否是并发修改了)

    解决方法:

    使用Iterator遍历的同时,使用Iterator.remove()删除你想删除的元素。另外也可以参考一下ListIterator,上面有很多针对List的方法。

    1 for( Iterator<ComType> iter = ComList.iterator(); iter.hasNext();){
    2     ComType com = iter.next();
    3     if ( !com.getName().contains("abc")){
    4         iter.remove(com);
    5     }
    6 }

    --- 共有 1 条评论 ---
    • 西部倒贴iter.remove(com); 这个地方错了吧? 应该是 iter.remove();吧 (1年前)   
    0
  • 棉花

    倒,不能这么遍历。

    for(int i = ComList.size() -1 ; i >= 0; i--){

    if(!ComList.get(i).getName.contains("abc")){

        CosList.remove(com);
    }

    }

    0
  • 棉花

    修正下

     

    for(int i = ComList.size() -1 ; i >= 0; i--){

    if(!ComList.get(i).getName.contains("abc")){

    CosList.remove(i);
    }

    }

    0
  • 红薯
    如果要在遍历过程中删除元素,应该用迭代器,同  @liuex 的方法 
    --- 共有 1 条评论 ---
    • 要做攻城师的志不用迭代器,在删除元素之后,马上break掉,也是可以的,这样更简单 (1年前)   
    0
  • 三毛々
    LZ在remove的时候居然没有给你抛出异常。真是奇怪。
    --- 共有 2 条评论 ---
    • 王国表回复 @java_cmm : 我这样弄就报错了,他们竟然会不报错? (1年前)   
    • helloming同感。。。 (1年前)   
    0
  • Monkey
    我又一个问题,楼主那样的代码不会出异常?  for-each是不能添加删除的,不然就出异常,  Iterator这个烂东西只能遍历,而且一旦容器发生变化这玩意就作废,继续访问就异常。
    --- 共有 1 条评论 ---
    0
  • 引用来自“liuex”的答案
    简化的for-each循环实际上只是一个语法糖,会被编译器转化成以下等价的代码:
    1 for( Iterator<ComType> iter = ComList.iterator(); iter.hasNext();){
    2     ComType com = iter.next();
    3     if ( !com.getName().contains("abc")){
    4         ComList.remove(com);
    5     }
    6 }

    也就是说,你在同时遍历和删除一个List,大多List实现是不允许这种操作的(某些List实现允许同时遍历和修改,例如CopyOnWriteArrayList),会抛并发修改异常。(具体可以参考ArrayList的源代码,ArrayList上面的ArrayList.iterator()操作会记录当前的修改次数modCount,remove/add操作会让修改次数自增,即modCount++,因此就能判断出来是否是并发修改了)

    解决方法:

    使用Iterator遍历的同时,使用Iterator.remove()删除你想删除的元素。另外也可以参考一下ListIterator,上面有很多针对List的方法。

    1 for( Iterator<ComType> iter = ComList.iterator(); iter.hasNext();){
    2     ComType com = iter.next();
    3     if ( !com.getName().contains("abc")){
    4         iter.remove(com);
    5     }
    6 }

    +1
    0
  • 爱coding

    1.集合在迭代期间,不能调用集合的add(),remove(),set()等方法,这就好像数鸡蛋,不允许在数鸡蛋的时候,突然把鸡蛋拿走了,

    2.如果需要迭代的时候删除集合元素,可以调用迭代器的删除方法,ite.remove()删除当前元素,而不是集合的remove方法。

    0
  • buptwhis

    一般地,还是用函数式的编程方式来解决这种问题比较好

    比如要过滤掉这上list的一些元素时,不是直接在这个list上面remove掉某个元素。而是在遍历这个list,把不需要过滤的元素收集起来加到一个新的list里面,完全避免这种问题

    --- 共有 2 条评论 ---
    0
  • java9
    用iterator来操作集合.你这种方法会改变集合的大小.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值