A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 朱盛文 于 2013-3-20 15:31 编辑
  1. import java.util.*;


  2. // 要求: 查找集合中有没有zhangsan这个字符串。如果有,则再添加一个lisi进去。

  3. public class ListDemo {
  4.         public static void main(String[] args) {
  5.                 // 创建集合对象
  6.                 List<String> list = new ArrayList<String>();

  7.                 list.add("zhaoliu");
  8.                 list.add("zhangsan");
  9.                 list.add("wangwu");

  10.                
  11.                 // 普通for循环
  12.                 for (int x = 0; x < list.size(); x++) {
  13.                         String s = list.get(x);
  14.                         if ("zhangsan".equals(s)) {
  15.                                 list.add("lisi");
  16.                         }
  17.                 }
  18.                 System.out.println("list:" + list);
  19.                
  20.                 System.out.println("******************************************");

  21.                 //增强for循环
  22.                 for(String s :list){
  23.                         if ("zhangsan".equals(s)) {
  24.                                 list.add("lisi");
  25.                         }
  26.                 }
  27.                 System.out.println("list:" + list);
  28.         }
  29. }
复制代码
运行结果如下:

用普通for时没有问题,增强for就出现了异常,请问该如何修改?

并发修改异常.jpg (27.96 KB, 下载次数: 65)

并发修改异常

并发修改异常

点评

如果你的问题已经得到解决,请及时将主题改为[已解决],如果还有问题请继续追问,谢谢  发表于 2013-3-20 12:25

评分

参与人数 1技术分 +1 收起 理由
洪建超 + 1

查看全部评分

5 个回复

倒序浏览
本帖最后由 blackcaismine 于 2013-3-20 11:04 编辑

刚看我也奇怪,于是在网上找了下原因,原来是因为:
在遍历集合过程中,增强for循环不能对集合本身进行操作
    for (String str : set) {
     set.remove(str);//错误!
    }
我把你的增强for循环改写了一下,里面改成System.out.println(s);,可以打印出zhangsan,说明除了增删操作外都可以正常使用

评分

参与人数 1技术分 +1 收起 理由
贾文泽 + 1

查看全部评分

回复 使用道具 举报
blackcaismine 发表于 2013-3-20 10:58
刚看我也奇怪,于是在网上找了下原因,原来是因为:
在遍历集合过程中,增强for循环不能对集合本身进行操作 ...

我试过直接打印输出可以正常操作,就是不明白这个增删该如何改
回复 使用道具 举报
类似于线程安全吧,使用Iterator迭代过程中也不可以使用集合自身的
增删方法,要使用迭代器的方法。原来增强for循环也有这个问题
回复 使用道具 举报
原因在这里啊:
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)

在AbstractList$Itr这个类中实现了Iterator接口,当使用增强的for循环时,
应该是使用迭代器进行迭代了,如果你在这期间使用了add方法的话,在ArrayList类中执行了这样的代码
  1. public boolean add(E e) {
  2.         ensureCapacity(size + 1);  // Increments modCount!!
  3.         elementData[size++] = e;
  4.         return true;
  5.     }
复制代码
  1. public void ensureCapacity(int minCapacity) {
  2.         modCount++;
  3.         int oldCapacity = elementData.length;
  4.         if (minCapacity > oldCapacity) {
  5.             Object oldData[] = elementData;
  6.             int newCapacity = (oldCapacity * 3)/2 + 1;
  7.                 if (newCapacity < minCapacity)
  8.                 newCapacity = minCapacity;
  9.             // minCapacity is usually close to size, so this is a win:
  10.             elementData = Arrays.copyOf(elementData, newCapacity);
  11.         }
  12.     }
复制代码
这里的modCount增加了,但是迭代器中的next方法时,
  1. public E next() {
  2.             checkForComodification();
  3.             try {
  4.                 E next = get(cursor);
  5.                 lastRet = cursor++;
  6.                 return next;
  7.             } catch (IndexOutOfBoundsException e) {
  8.                 checkForComodification();
  9.                 throw new NoSuchElementException();
  10.             }
  11.         }
复制代码
先checkForComodification();
  1. final void checkForComodification() {
  2.             if (modCount != expectedModCount)
  3.                 throw new ConcurrentModificationException();
  4.         }
  5.     }
复制代码
因此抛出了异常。。。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
在遍历集合时,增强for的遍历是封装了迭代器的试遍历方式
如果你明白为什么迭代时不能使用用集合的方式添加或删除元素,应该会明白这里为什么会发生异常了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马