栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java 迭代器 Iterator

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java 迭代器 Iterator

迭代器的作用就是用来遍历集合的

那么,在遍历的过程中,是否允许其他人来修改集合?

有两种处理策略:Fail-Fast 与 Fail-Safe

1.Fail-Fast

fail-fast 一旦发现遍历的同时其它人来修改,则立刻抛异常

ArrayList 是 fail-fast 的典型代表,遍历的同时不能修改,尽快失败

测试代码

创建一个ArrayList集合并添加元素,遍历输出

添加断点,在遍历至 C 时,可以debug,模拟另一个线程,修改list,添加一个元素

查看 list 集合,由4个元素,变成了5个元素

放开断点,将 C 遍历输出后,下一轮循环时,报错(并发修改异常) java.util.ConcurrentModificationException ,

原理:

for循环会用到底层的迭代器,首次循环的时候,会创建一个迭代器对象

创建一个迭代器对象时,初始化迭代器的一些成员变量

modCount是 list数组 集合的成员变量,记录 list数组 被修改了几次(现在数值是4,因为add了4次)

expectedModCount 是迭代器的成员变量,记录迭代初始时,list数组 修改的次数 

接下来会调用迭代器的hasNext()、next()方法,向下移动,每次调用next()方法时,会调用checkForComodification(),对 expectedModCount 做检查

当发现,迭代开始时的list数组修改次数(4),与list数组修改次数(5)不一致时,抛出异常

即,通过判断循环开始时list数组的修改次数,与循环中的list数组的修改次数是否相等,来判断循环过程中,list数组是否发生修改

如何查看list数组的modCount?

idea控制台,默认显示list数组的元素,进行一下修改

 将List选项,改为Object选项,就能看到一些数的成员变量

 2.Fail-Safe

fail-safe 发现遍历的同时其它人来修改,应当能有应对策略,例如牺牲一致性来让整个遍历运行完成

CopyOnWriteArrayList 是 fail-safe 的典型代表,遍历的同时可以修改,原理是读写分离

测试代码

创建一个CopyOnWriteArrayList集合并添加元素,遍历输出

添加断点,在遍历至 C 时,可以debug,模拟另一个线程,修改list,添加一个元素,查看 list 集合,由4个元素,变成了5个元素

放开全部断点,遍历输出了4个,但集合有5个元素

虽然没有报错,但是牺牲了一致性

原理:

在首次循环,会创建迭代器对象,不过对象变成了COWIterator

进入构造器的构造方法,会把当前正在遍历的数组记录下来,保存在snapshot成员变量中

 依然创建集合,debug,在循环至C时,添加元素,发现list数组的元素变成了5个

进入迭代器看看,发现是初始的4个元素

为什么呢?

需要看下add的源码

注意这一句,add时,将原数组复制了一份,生成一个新数组,并长度+1,然后将新元素放到新数组的最后一个 

每次添加新元素时,都会复制出一个新数组,添加结束后,就会把初始数组替换成新数组,但在遍历过程中,使用的是初始数组

添加是一个数组,遍历时另一数组,二者互补干扰

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1031518.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号