java集合的遍历删除。
案例
-
使用普通for循环遍历集合
//以下代码不会有任何问题 List<Integer> list = new ArrayList(); list.add(1); list.add(2); list.add(3); int listSize = list.size(); for (int i = 0; i < listSize; i++) { iterator.remove();//或者 list.remove(0);或者使用,list.remove(list.get(0)); } System.out.println(list.size());
-
当你使用集合的forEach()遍历集合时,
//这里会报异常: java.util.ConcurrentModificationException List<Integer> list = new ArrayList(); list .add(1); list.add(2); list.add(3); for (Integer integer : list) { list.remove(integer); }
这是因为forEach底层用的是iterator迭代器
-
当使用iterator迭代器遍历集合时
List<Integer> integerList=new ArrayList<>(); Iterator<Integer> iterator = integerList.iterator(); while (iterator.hasNext()){ Integer integer=iterator.next(); integerList.remove(integer);//这个方式移除,报异常java.util.ConcurrentModificationException iterator.remove(); //用这个方式没有问题 }
原因:
这里查看ArrayList实现iterator的源码,注意iterator的next()和remove()方法。
你会发现,iterator的next()和remove()方法,都调用了checkForComodification(),当ArrayList的modCount (修改次数)!= expectedModCount(迭代器修改次数)时,会抛异常,当你调用iterator的remove()方法,会同步两个修改次数,而ArrayList不会同步,所以会抛异常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; Itr() {} public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification();//检查集合修改次数 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]; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification();//检查集合修改次数 try { ArrayList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount;//这里同步了两个修改次数 } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } @Override @SuppressWarnings("unchecked") public void forEachRemaining(Consumer<? super E> consumer) { Objects.requireNonNull(consumer); final int size = ArrayList.this.size; int i = cursor; if (i >= size) { return; } final Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) { throw new ConcurrentModificationException(); } while (i != size && modCount == expectedModCount) { consumer.accept((E) elementData[i++]); } // update once at end of iteration to reduce heap write traffic cursor = i; lastRet = i - 1; checkForComodification(); } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }