1.写出下面的输出结果

public class test{
  public static void main(String [] args)

   List<String> list = new ArrayList<String>();

   for (int i = 0; i < 10; i++) {
     list.add(String.valueOf(i));
   }
   for(String s : list){
    if(s.equals("3")){
      list.remove(s);
    }
   }
  System.out.println(list.size());

  }

}

正确的输出:发生了并发的错误

java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at test.main(test.java:35)

在这里for(String s : list){}的实质还是Iterator接口。

上面这段代码等价于下面:

Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
  String itString = (String)iterator.next();
  if (itString.equals("3")) {
    list.remove(itString); --这里会报错

    //iterator.remove();---这里不会报错

  }
}

所以我们来看看 list.iterator();的源码就知道为什么了

public Iterator<E> iterator() {
  return new Itr();
}

/**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator<E> {
  int cursor; // index of next element to return
  int lastRet = -1; // index of last element returned; -1 if no such
  int expectedModCount = modCount;

  public boolean hasNext() {
    return cursor != size;
  }

  @SuppressWarnings("unchecked")
  public E next() {
    checkForComodification();
    int i = cursor;
    if (i >= size)
      throw new NoSuchElementException();
    Object[] elementData = ArrayList.this.elementData;
    if (i >= elementData.length)
      throw new ConcurrentModificationException();
    cursor = i + 1;
    return (E) elementData[lastRet = i];
  }

  public void remove() {
    if (lastRet < 0)
      throw new IllegalStateException();
    checkForComodification();

    try {
      ArrayList.this.remove(lastRet);
      cursor = lastRet;
      lastRet = -1;
      expectedModCount = modCount;
    } catch (IndexOutOfBoundsException ex) {
      throw new ConcurrentModificationException();
    }
  }

  final void checkForComodification() {
    if (modCount != expectedModCount)
      throw new ConcurrentModificationException();
  }
}

从源码上我们可以看出,当我们调用next()方法的时候有一个检查modCount != expectedModCount;然后我们再来看看ArrayList的remove方法

public boolean remove(Object o) {
  if (o == null) {
    for (int index = 0; index < size; index++)
      if (elementData[index] == null) {
        fastRemove(index);
        return true;
      }
  } else {
  for (int index = 0; index < size; index++)
    if (o.equals(elementData[index])) {
      fastRemove(index);
      return true;
    }
  }
  return false;
}

/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
  modCount++;
  int numMoved = size - index - 1;
  if (numMoved > 0)
    System.arraycopy(elementData, index+1, elementData, index,
    numMoved);
  elementData[--size] = null; // Let gc do its work
}

从上面的代码中可以看出当我们进行remove的时候modeCount的值发生了变化,这就导致和expectedModCount的值相等了,故报错。

从源码中我们还得知,在clear方法,add方法,addAll方法,removeRange方法时都会导致modeCount的值发生变化。

所以当我们想在循环中对List进行删除时不能用List的remove*方法。但是可以用iterator.remove();从上面的源码中我们可以知道这个方法中进行了

expectedModCount=ModCount对expectedModCount重新赋值。

JAVA循环迭代中删除或添加集合数据报java.util.ConcurrentModificationException错误的更多相关文章

  1. 遍历List过程中删除操作报java.util.ConcurrentModificationException错误

    1:遍历List 同时 remove 元素,出现java.util.ConcurrentModificationException错误 @Test public void test3(){ List& ...

  2. Java循环遍历中直接修改遍历对象

    Java 循环遍历中直接修改遍历对象如下,会报异常: for (ShopBaseInfo sp: sourceList) { if(sp.getId()==5){ sourceList.remove( ...

  3. Java中删除第一个集合中以某某开头的元素,删除第二个集合中以某某结尾的元素,并合并成一个集合

    import java.util.ArrayList; import java.util.List; public class Test { public static void main(Strin ...

  4. 【java】TreeMap/HashMap的循环迭代中 keySet和entrySet和forEach方式 + map的几种迭代方式

    参考链接:https://www.cnblogs.com/crazyacking/p/5573528.html ================================== java紫色代表迭 ...

  5. java ArrayList迭代过程中删除

    第一种迭代删除方式: 第二种迭代删除方式: 第三种迭代删除: 第四种迭代删除: 第五种迭代删除: 第六种: ArrayList中remove()方法的机制,首先看源码: 真正的删除操作在fastRem ...

  6. cmd中删除、添加、修改注册表命令

    转自:http://www.jb51.net/article/30586.htm regedit的运行参数 REGEDIT [/L:system] [/R:user] filename1 REGEDI ...

  7. js实现在表格中删除和添加一行

    <!DOCTYPE html><html> <head> <title> new document </title> <meta ht ...

  8. For循环List中删除正确的方式

    单线程public class Test { public static void main(String[] args) { ArrayList<Integer> list = new ...

  9. Java 遍历List中删除的解决方法

随机推荐

  1. [Linux]非常方便的上传下载文件工具rz和sz

     linux上非常方便的上传下载文件工具rz和sz (本文适合linux入门的朋友) [一般用于SecureCRT ssh中使用] █ 法一:直接用yum安装lrzsz(推荐) yum insta ...

  2. luogu1967 货车运输 最大瓶颈生成树

    题目大意 给出一张图,给出q对点,求这两个点间权值最小边最大的路径,输出这个最小边权. 题解 我们先一条一条边建图.当建立的边使得图中形成环时,因为环中的每个节点只考虑是否连通和瓶颈大小,要想互相连通 ...

  3. Triangle LOVE(拓扑排序)

    Triangle LOVE Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/65536K (Java/Other) Total ...

  4. [转载]ROS_LOG保存方法

    原文地址:ROS_LOG保存方法作者:东咚... 把Service中的WWW的IP设置为允许日志保存服务器访问的范围 System->Logging,点击 "Actions" ...

  5. Email非正则表达式的判断

    判断一个邮件是否合法,我们除了可以使用正则表达四以外还可以利用,Email地址的规律进行判断,那么一个合法的Email有哪些要求昵?具体如下: 必须有@与. @必须在第一个.之前 @与.不能连在一起 ...

  6. 在量化金融中15个最流行的Python数据分析库

    Python是当今应用最广泛的编程语言之一,以其效率和代码可读性著称.作为一个科学数据的编程语言,Python介于R和java之间,前者主要集中在数据分析和可视化,而后者主要应用于大型应用.这种灵活性 ...

  7. 数据科学的完整学习路径(Python版)

    转载自:http://python.jobbole.com/80981/ 英文(原文)连接:https://www.analyticsvidhya.com/learning-paths-data-sc ...

  8. Python3没有dict.has_key方法

    最近开始学习Python,安装上最新的Python3.3.3照书敲了一个小程序结果报错 'dict' object has no attribute 'has_key' 上网查也找不到解决办法,后来发 ...

  9. C# txt文件操作

    //打开文件到流 FileStream fs=new FileStream(path,FileMode.Open,FileAccess.ReadWrite); //写文件流的方法 StreamWrit ...

  10. MapReduce架构与生命周期

    MapReduce架构与生命周期 概述:MapReduce是hadoop的核心组件之一,可以通过MapReduce很容易在hadoop平台上进行分布式的计算编程.本文组织结果如下:首先对MapRedu ...