Java Iterator ListIterator 迭代器 以及 并发修改异常 ConcurrentModificationException
来源:互联网 发布:c语言排队系统 编辑:程序博客网 时间:2024/06/05 11:14
迭代器内部定义了一个 cursor 变量,用来指示当前遍历到了什么位置。每次调用 next() 或 previous() 对该值做出相应的 递增或递减 操作,以此实现顺序迭代。
当调用 hasNext() 方法时,判断 cursor 变量是否等于集合大小,如果不等于,说明后面还有元素可以正序迭代。
当调用 hasPrevious() 方法时,判断 cursor 变量是否小于 0 ,如果不等于,说明前面还有元素可以倒序迭代。
Iterator 迭代器
方法示例
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
运行结果
Iterator 的方法
方法 功能 hasNext()判断集合列表中是否还有可以迭代的元素next()返回下一个元素remove()移除最近返回的一个元素
ListIterator 迭代器
方法示例
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 运行结果
ListIterator 的方法
方法 功能 hasNext()判断是否还有下一个元素可以迭代next()返回下一个元素hasPrevious()判断是否还有上一个元素可以迭代previous()返回上一个元素add()返回上一个元素set(E e)用指定的元素替换最近返回的元素remove()移除最近返回的元素
并发修改异常
简单来讲,并发修改异常就是在对集合元素进行迭代的时候,集合本身发生了改变,所以抛出此异常。先来看一个示例。
示例
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
运行结果
原因
- 上面已经提到,并发修改异常 是在迭代过程中,被迭代的集合发生了变化才引发的。那么看下面代码中用 蓝色 标识的代码,这里显然对集合中的元素进行了 移除操作。
- 需要注意的是,该异常并不是移除操作引发的 ,而是上面用 红色 标识的代码,也就是下一次循环去获取集合元素的时候引发的。具体是怎么回事这要讲一下源码,看下图。
- 源代码 next() 方法中,调用了一个 checkForComodification() 方法,这是什么呢? 继续跟下去看一下。
看上图,代码显示,如果 modCount 不等于 expectedModCount 则抛出 并发修改异常 。那么这两个变量都是什么意思呢?我们继续分析源码。
集合在创建时: modCount 的值默认是 0 那么这个值在什么情况下会发生变化呢?首先,我们看添加元素 add() 方法。
这里调用了一个 ensureCapacityInternal() 方法,跟下去看一下。看上面的图片,在 调用 ensureCapacityInternal() 方法后,ensureCapacityInternal() 方法里又调用了一个 ensureExplicitCapacity() 方法,而 modCount 值的改变就是发生在这个方法里,当然,在 add()方法调用 ensureCapacityInternal() 之前,元素的添加操作就以及完成了, 实际上包括 remove()、set() 操作最后都会递增 modCound。也就是说,只要对集合进行了操作,这个 modCount 值就会递增一次。
现在,我们搞清楚了 modCount 是怎么回事,那 expectedModCount 又是怎么回事呢?看下图。
当我们调用集合的 iterator() 方法获得迭代器时,底层实际上是给我们 new 了一个 Itr 内部类对象,这个内部类实现了 Iterator 接口。
看上图箭头标识 1 的位置,在创建迭代器 Itr 对象的时候,先用 expectedModCount 把集合的 modCount 值记录下来。
讲到这里,再返回上面看一下前面说到的 调用迭代器的 next() 为什么引发 并发修改异常 就明白怎么回事了。
- 上面已经提到,并发修改异常 是在迭代过程中,被迭代的集合发生了变化才引发的。那么看下面代码中用 蓝色 标识的代码,这里显然对集合中的元素进行了 移除操作。
总结
实现了 Iterator 迭代器接口的集合都可以使用迭代器对其元素进行遍历。
ListIterator 可以再迭代时对集合进行 add、set、remove 操作,而 Iterator 迭代器只能在迭代时对集合进行 remove 操作。
不允许在迭代时对集合进行操作,当然,使用迭代器本身提供的方法除外,原因这里不再图文分析,简单说一下吧,在使用迭代器本身提供的方法对集合操作后,expectedModCount 的值也会相应递增,所以下次检查是就不会有问题。感兴趣的朋友可以自己去看一下源代码。
- Java Iterator 和 ListIterator 迭代器 以及 并发修改异常 ConcurrentModificationException
- Java Iterator ListIterator 迭代器 以及 并发修改异常 ConcurrentModificationException
- Java并发修改异常ConcurrentModificationException
- JAVA ConcurrentModificationException并发修改异常
- 迭代器并发修改异常ConcurrentModificationException
- java面试题15--迭代器并发修改异常ConcurrentModificationException
- ConcurrentModificationException并发修改异常
- ConcurrentModificationException并发修改异常
- java.util.ConcurrentModificationException:并发修改异常!
- java.util.ConcurrentModificationException 并发修改异常处理
- ConcurrentModificationException异常以及iterator迭代器的使用原理
- linkedlist中使用迭代器出现并发修改异常,ConcurrentModificationException异常
- 理解和解决Java并发修改异常ConcurrentModificationException
- Java集合之ConcurrentModificationException(并发修改异常)分析
- 关于java集合的遍历以及ConcurrentModificationException(并发操作异常)
- 关于迭代器的在集合遍历中发生的并发修改异常(java.util.ConcurrentModificationException
- Java Iterator与ListIterator
- java:Iterator和ListIterator
- JS中“创建对象”及“通过原型创建对象”浅析
- 剑指Offer——(43)左旋转字符串
- Regular polygon HDU
- CNN 神经网络介绍
- Lua基础之table详解
- Java Iterator ListIterator 迭代器 以及 并发修改异常 ConcurrentModificationException
- Mac java环境变量配置过程记录
- [并查集+启发式合并]BZOJ 2733——[HNOI2012]永无乡
- Material design的学习笔记
- library not loaded 错误
- intent传递数据太大,报TransactionTooLargeException异常
- 在CentOS7中设置Tomcat开机自启动
- 关于unity3d for ARkit(一)
- java循环和switch混合简单应用