对List元素迭代删除的注意事项以及三个方法

来源:互联网 发布:免费视频网站源码 编辑:程序博客网 时间:2024/06/06 00:50

有一个List,里面存储1-100000的数,,写出几种删除是偶数的元素的代码
第一印象是找到list中偶数,对其直接删除

for(int num:list){            if(num%2==0) list.remove(num);        }

结果就报了concurrentModificationException,并发修改异常
我们都知道,使用for循环遍历集合,内部会走Iterator,即判断hasNext之后,使用next移动光标到下一个。
看了一下hasNext与next的源码

private class Itr implements Iterator<E> { int cursor;       // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; public boolean hasNext() {            return cursor != size;//游标不等于元素个数就是还有下一个 }public E next() {     checkForComodification();//check是否并发修改      int i = cursor;      if (i >= size)          throw new NoSuchElementException();      Object[] elementData = ArrayList.this.elementData;      if (i >= elementData.length)          throw new ConcurrentModificationException();      cursor = i + 1;      return (E) elementData[lastRet = i];  } final void checkForComodification() {            if (modCount != expectedModCount)                throw new ConcurrentModificationException();  }}

**modCount是集合添加元素、删除元素的次数,expectedModCount是预期的修改次数。
每次进入next都会判断modCount与expectedModCount是否相等,不相等则抛出并发修改异常**
可以想到,假设起始在list添加100000数据,则modCount为100000,expectedModCount也初始为100000,然而对list直接remove一次之后,删除元素次数就+1了,那么expectedModCount=100001!=modCount,所以报错

而使用Iterator删除元素就不会报错了,比如

方法一:

Iterator<Integer> it = list.iterator();        while(it.hasNext()){            int i=it.next();            if(i%2==0) it.remove();        }

花费600ms
使用it.remove()来删除每一个符合的元素,Iterator会自动修改expectedModCount,使modCount与之相等。

方法二:
先找到符合的元素组成集合,在一次性removeAll

List<Integer> list3 = new ArrayList<>();        for(int num:list){            if(num%2==0){                list3.add(num);            }        }list.removeAll(list3);

十万条数据花费3000ms+

看到画了3000ms,我面红耳赤,这tm,脑子有问题了,这又是写新集合又是删原集合,还是个ArrayList而不是LinkedList,怎么可能更快,

于是
方法三:
。。。。。突然发现上面代码的list3反过来不就是结果嘛。

List<Integer> list2 = new ArrayList<Integer>();        while(it.hasNext()){            int i=it.next();            if(i%2!=0) list2.add(i);        }

这里的list2就是“删完”偶数的list
耗时10ms

原创粉丝点击