近期在学集合时学到了iterator迭代器那里,在一次做练习时遇到了这样一个问题,代码如下
ArrayList a1=new ArrayList();
a1.add("a");
a1.add("b");
a1.add("c");
a1.add("d");
Iterator it =a1.iterator();
while(it.hasNext()) {
String s=(String)it.next();
if(s.equals("c")) {
a1.add("c1");
}
}
System.out.println(a1);
}
问我会输出什么,那我一开始当然想错了,系统报出错误
然后就想为什么,到网上去搜了一下,大佬给出的解释是Fail-Fast 机制 (如果在使用迭代器的过程中有其他线程修改了map,那么将抛出ConcurrentModificationException,这就是所谓fail-fast策略。这一策略在源码中的实现是通过 modCount 域,modCount 顾名思义就是修改次数,对HashMap 内容的修改都将增加这个值,那么在迭代器初始化过程中会将这个值赋给迭代器的 expectedModCount。在迭代过程中,判断 modCount 跟 expectedModCount 是否相等,如果不相等就表示已经有其他线程修改了 Map:注意到 modCount 声明为 volatile,保证线程之间修改的可见性。
————————————————
版权声明:本文为CSDN博主「魏福成」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012926924/article/details/50452411
附上源码,方便理解
这又让我想到了一个java面试题 Iterable和iterator区别
那么当我们遇到了这题,可以根据这个说说,相信会为你增分不少
都是接口,iterable是collection的父接口,iterator是iterable未实现方法的返回值类型
对集合元素遍历时进行增删时会有异常出现(原因是集合内部的每一个更新方法中都包含一行代码modCount++)在获取迭代器时会首先将改值缓存到iterator对象的成员变量中,接下来对集合使用内部的更新方法操作元素时每次都会重新修改modCount值(除非调用自己的remove),因此一旦更新元素,导致迭代器检查2个值是否一致,不一致抛出异常
解决方案
- 使用迭代器的remove
- 找到满足的条件的元素之后结束循环
- 更改元素不只一个时,可以先用数组存储,然后删除数组
其实知道了这个是迭代器里的东西时,那么集合里所有东西基本上都涉及到它了。HashMap的底层实现也用到它了,大家有兴趣的话可以去追一下源码看看