ArrayList迭代删除元素的小坑

项目场景:

笔试遇到了一个看似很简单的题目:

        一个ArrayList集合有四个整数元素,要求删除掉其中大于10的元素。


问题描述

看到这个题目,脑子一激灵,这还不简单?直接写下以下代码:

List<Integer> list = new ArrayList<Integer>();
list.add(6);
list.add(12);
list.add(2);
list.add(8);
for(Integer i:list){
    if(i>10){
        list.remove(i);
    }
}
System.out.println(list);
然后果断就悲剧了,运行结果如下:

由此可见这样写是不允许的,我这道题应该是悲剧了,想想也是,怎么可能这么简单。


原因分析:

ArrayList的父类AbstarctList中有一个域modCount,每次对集合进行修改(增添、删除元素)时modCount都会+1。

对于集合而言,增强for循环的实现原理就是迭代器Iterator,在这里,迭代ArrayList的Iterator中有一个变量expectedModCount,该变量会初始化和modCount相等,但当对集合进行插入,删除操作,modCount会改变,就会造成expectedModCount!=modCount,此时就会抛出java.util.ConcurrentModificationException异常,是在checkForComodification方法中,代码如下:

private void checkForComodification(int expectedModCount) {
    if (this.modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
}


解决方案:

1.在使用迭代器遍历时,可使用迭代器的remove方法,因为Iterator的remove方法中 有如下的操作:

expectedModCount = modCount;

所以避免了ConcurrentModificationException的异常。

List<Integer> list = new ArrayList<Integer>();
list.add(6);
list.add(12);
list.add(2);
list.add(8);
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
    Integer i =iterator.next();
    if(i>10){
        iterator.remove();
    }
}
System.out.println(list);

2.采用普通for循环,通过索引的方式删除元素,需要注意的是我这里采用的是倒序遍历,如果正序遍历的话要注意索引的变化

List<Integer> list = new ArrayList<Integer>();
list.add(6);
list.add(12);
list.add(2);
list.add(8);
for (int i = 0; i < list.size(); i++) {
   Integer num = list.get(list.size() - 1 - i);
   if(num>10) {
       list.remove(list.size() - 1 - i);
   }
}
System.out.println(list);

以上两种方法都可以正常输出结果:

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值