for 循环你真的会用嘛?

这是一篇纯新手贴,欢迎拍砖。今天一个同事小王跑来问我为什么像下面程序一这样写就不会抛异常。

 

List<String> list = new ArrayList<String>();
list.add("1");
for(int i=0; i<list.size(); i++)
{
     list.remove(0);
}

 

然而向下面程序二这样写就会抛 java.util.ConcurrentModificationException 异常。

List<String> list = new ArrayList<String>();
list.add("1");
for(String str : list ){
    list.remove(0);
}

当时我进入List的源代码跟他解答了一下:

1,List中有一个 modCount 参数。

 

/**
  * The modCount value that the iterator believes that the backing
  * List should have.  If this expectation is violated, the iterator
  * has detected concurrent modification.
  */

int expectedModCount = modCount;

 

 

 

2,当你remove的时候 modCount 的值会改变。modCount++;

     (事实证明你add的时候modCount的值也会改变。)

3,for(String str : list) 用到了iterator() 方法。在 iterator.next() 操作中会调用 checkForComodification();

4,checkForComodification 的时候 会判断 modCount != expectedModCount
     if (modCount != expectedModCount)

      throw new ConcurrentModificationException();

所以,由于你在for(String str : list)中改变了list的结构(remove,add等都不行),所以就会抛ConcurrentModificationException 异常了。

 

本以为解答清楚啦。。。。没想到我同事小王又问。。为什么? 为什么iterator() 方法中要判断modCount != expectedModCount。为什么不能在for(String str : list) 中更改list的结构。。。。。。

 

好吧。上网搜索Iterator的工作机制。。。。。。。Iterator是工作在一个独立的线程中,并且拥有一个 mutex锁,就是说Iterator在工作的时候,是不允许被迭代的对象被改变的。Iterator被创建的时候,建立了一个内存索引表(单链表),这个索引表指向原来的对象,当原来的对象数量改变的时候,这个索引表的内容没有同步改变,所以当索引指针往下移动的时候,便找不到要迭代的对象,于是产生错误。 Iterator是一个单向不可变,只能顺序读取,不能逆序操作的数据结构,当 Iterator指向的原始数据发生变化时,Iterator就会抛异常。

同事小王又问 为什么? 为什么Iterator是索引表没有同步改变?

那个小王他们叫我吃午饭呢。。。那个实在不行你去 Iteye 上发个帖子问问啥的。。。。。

我先吃饭去啦。。。回来再说哈。。。。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值