摘要:单线程的迭代过程中删除集合元素以上代码会出现如下异常从后往前看第行代码我们在执行代码行时调用了这个是调用返回的对象这个对象的方法如下图方法首先它会调用这个方法这个方法很简单就是比较这两个值是不是相等不相等就抛出异常如下图这两个值为什么会不相
单线程的Iterator迭代过程中删除集合元素
public class TestIterator { public static void main(String[] args) { Listlist = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); list.add("5"); list.add("6"); Iterator it = list.iterator(); while (it.hasNext()) { String next = it.next(); if("3".equals(next)) { list.remove(3); } System.out.println(next); } } }
以上代码会出现如下异常
Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) at java.util.ArrayList$Itr.next(ArrayList.java:851) at caoyan.test.TestIterator.main(TestIterator.java:22)
从后往前看:
TestIterator第22行代码:
String next = it.next();
我们在执行代码22行时调用了it.next();这个it是ArrayList调用iterator()返回的对象;这个对象的next()方法如下图:
public E next() { checkForComodification(); ...
next()方法首先它会调用checkForComodification()这个方法,这个方法很简单,就是比较expectedModCount , modCount 这两个值是不是相等;不相等就抛出异常;如下图:
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
这两个值为什么会不相等,它们各自代表什么含义呢,我们看ArrayList的iterator()方法:
public Iteratoriterator() { return new Itr(); } /** * An optimized version of AbstractList.Itr */ private class Itr implements Iterator { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount;
Arraylist的iterator()方法,直接创建了一个私有的内部类Itr的对象;expectedModCount 就是定义在这个Itr中的成员变量,而且,在初始化的时候,将modCount赋值给expectedModCount,说明在刚生成Iterator的时候这两个值是相等的.modCount是定义在哪里呢,看下面源码
public class ArrayListextends AbstractList ... protected transient int modCount = 0;
modCount是AbstractList的成员变量,ArrayList继承下来了.所以modCount代表ArrayList的实际长度.
当我们在iterator的迭代过程中改变了ArrayList的长度,就导致modCount变了,而expectedModCount 没有变,导致不相等报错
可是为什么用iterator的remove方法就不报错呢,我们看Remove方法():
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(); } }
可以看到,ArrayList在删除元素后,expectedModCount = modCount;重新赋值,让这两个值相等了.所以,remove方法不会抛出这个异常
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/67499.html
摘要:单线程的迭代过程中删除集合元素以上代码会出现如下异常从后往前看第行代码我们在执行代码行时调用了这个是调用返回的对象这个对象的方法如下图方法首先它会调用这个方法这个方法很简单就是比较这两个值是不是相等不相等就抛出异常如下图这两个值为什么会不相 单线程的Iterator迭代过程中删除集合元素 public class TestIterator { public static voi...
摘要:单线程的迭代过程中删除集合元素以上代码会出现如下异常从后往前看第行代码我们在执行代码行时调用了这个是调用返回的对象这个对象的方法如下图方法首先它会调用这个方法这个方法很简单就是比较这两个值是不是相等不相等就抛出异常如下图这两个值为什么会不相 单线程的Iterator迭代过程中删除集合元素 public class TestIterator { public static voi...
摘要:迭代器智能吗第一步,将列表中的根节点找出来。源码翻开中迭代器的源码。在迭代器对象执行操作之前,都会执行方法,以判断当前操作下是否安全。 引言 ConcurrentModificationException这个异常大家都很熟悉,当在forEach进行删除时都会出现该异常。 如果你还不了解,请参考澍澍的博客:关于在list循环的过程中进行删除的处理 - 晨澍的博客 showImg(http...
摘要:迭代器智能吗第一步,将列表中的根节点找出来。源码翻开中迭代器的源码。在迭代器对象执行操作之前,都会执行方法,以判断当前操作下是否安全。 引言 ConcurrentModificationException这个异常大家都很熟悉,当在forEach进行删除时都会出现该异常。 如果你还不了解,请参考澍澍的博客:关于在list循环的过程中进行删除的处理 - 晨澍的博客 showImg(http...
摘要:源码分析构造方法有两个构造方法,一个是无参,另一个需传入初始容量值。所以我们可以把上面的代码转换一下,等价于下面形式这个时候,我们再去分析一下的迭代器源码就能找出原因。原因是删除元素后,元素计数器,而迭代器中的也等于,从而导致返回。 1.概述 ArrayList 是一种变长的集合类,基于定长数组实现。ArrayList 允许空值和重复元素,当往 ArrayList 中添加的元素数量大于...
阅读 3838·2021-09-10 11:22
阅读 2304·2021-09-03 10:30
阅读 3611·2019-08-30 15:55
阅读 1819·2019-08-30 15:44
阅读 824·2019-08-30 15:44
阅读 533·2019-08-30 14:04
阅读 3026·2019-08-29 17:18
阅读 1247·2019-08-29 15:04