BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / java / #56440同步于 2017/5/31
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖

一个java Iterator问题

zcy19941015
2017/5/31镜像同步18 回复
代码1:这段代码会报一个java.util.ConcurrentModificationException public class Test { public static void main(String args[]){ List<String> list = new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); for (String i : list){ if (i.equals("a")){ list.remove("a"); } } } } 代码2:这段代码就没问题了 public class Test { public static void main(String args[]){ List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); for (Integer i : list){ if (i == 2){ list.remove(list.indexOf(2)); } } for (Integer i : list){ System.out.print(i); } } } 请问各位大大这是为什么?
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
fa520875机器人#1 · 2017/5/31
你直接删除一个元素 觉得没问题吗?这样他后面的元素不就前移了一位了吗
fa520875机器人#2 · 2017/5/31
百度结果是元素在使用时发生了并发修改
intmain机器人#3 · 2017/5/31
用迭代器迭代容器的同时还修改了容器(remove),会导致原有的迭代器失效
zcy19941015机器人#4 · 2017/5/31
但问题是第二个代码没错啊 【 在 fa520875 的大作中提到: 】 : 你直接删除一个元素 觉得没问题吗?这样他后面的元素不就前移了一位了吗
zcy19941015机器人#5 · 2017/5/31
但问题是第二个代码没错啊 【 在 intmain 的大作中提到: 】 : 用迭代器迭代容器的同时还修改了容器(remove),会导致原有的迭代器失效
ccyingzi2009机器人#6 · 2017/5/31
第二个崩溃不是必现的。 不过很大概率崩溃。 【 在 zcy19941015 的大作中提到: 】 : 但问题是第二个代码没错啊 :
cbd机器人#7 · 2017/5/31
你的两段测试代码中都用到了foreach循环遍历list集合,实际上foreach循环是JavaC编译器提供的一个语法糖,在编译后会替换为迭代器的形式,也就是for(String str : list)会变为for(Iterator iter = list.iterator(); iter.hasNext(); str = iter.next()),ArrayList不是线程安全的,内部实际上维护了一个modCount变量,记录对List结构进行修改的次数,迭代器进行迭代时,先hasNext()判断还有下一个元素没被访问时,再next()迭代下一个元素,在next()内部,实际上会判断刚才提到的modCount变量是否还是预期值,如果不是,就说明在迭代时有线程(可能是当前迭代线程,就是你的第一个例子的情况,也有可能是其它线程)修改了集合结构(add,remove),就会直接抛出ConcurrentModificationException,终止迭代。 你的第二个例子,在第一个foreach中,会remove掉index为2的元素,而list中只有3个元素,也就是删掉了最后一个元素,而在开始第三次迭代时,同样会先hasNext()判断是否还有下一个元素,此时肯定为false,所以也就不会再next()了,迭代正常结束。 看一下ArrayList的源码就知道原因了。 ps:手机码字,可能不通顺,仅供参考啊…… 发自「贵邮」
dss886机器人#8 · 2017/5/31
楼上基本都说清楚了
nihaoa机器人#9 · 2017/5/31
第二个例子中应该删除的是2吧,list.indexOf(2)返回的是2的索引值,list.remove(list.indexOf(2))应该是把2删除了吧,最后输出是1,3呀。 【 在 cbd 的大作中提到: 】 : 你的两段测试代码中都用到了foreach循环遍历list集合,实际上foreach循环是JavaC编译器提供的一个语法糖,在编译后会替换为迭代器的形式,也就是for(String str : list)会变为for(Iterator iter = list.iterator(); iter.hasNext(); str = iter.next()),ArrayList不是线程安全的,内部实际上维护了一个modCount变量,记录对List结构进行修改的次数,迭代器进行迭代时,先hasNext()判断还有下一个元素没被访问时,再next()迭代下一个元素,在next()内部,实际上会判断刚才提到的modCount变量是否还是预期值,如果不是,就说明在迭代时有线程(可能是当前迭代线程,就是你的第一个例子的情况,也有可能是其它线程)修改了集合结构(add,remove),就会直接抛出ConcurrentModificationException,终止迭代。 : 你的第二个例子,在第一个foreach中,会remove掉index为2的元素,而list中只有3个元素,也就是删掉了最后一个元素,而在开始第三次迭代时,同样会先hasNext()判断是否还有下一个元素,此时肯定为false,所以也就不会再next()了,迭代正常结束。 : 看一下ArrayList的源码就知道原因了。 : ...................