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. 第一次Java作业——简单的登录界面

    千里之行,始于足下,从小做起,一点一滴学编程. import javax.swing.*; import java.awt.*; public class Homework{ public stati ...

  2. 什么是 SHTML

    什么是 SHTML 使用SSI(Server Side Include)的html文件扩展名,SSI(Server Side Include),通常称为“服务器端嵌入”或者叫“服务器端包含”,是一种类 ...

  3. oc19--继承1

    // // Phone.h // day13 #import <Foundation/Foundation.h> // 被继承的这个类我们称之为父类/ 超类 @interface Phon ...

  4. The Euler function(hdoj --2824-欧拉函数)

    The Euler function Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  5. php 判断字符串包含中文(转)

    $str = "测试中文"; echo $str; echo "<hr>"; //if (preg_match("/^[".ch ...

  6. 什么是CAS?

    CAS(Compare-and-Swap),即比较并替换,是一种实现并发算法时常用到的技术,Java并发包中的很多类都使用了CAS技术.CAS需要有3个操作数:内存地址V,旧的预期值A,即将要更新的目 ...

  7. php对文件/目录操作的基础知识(图解)

    具体的如下图所示:

  8. mysql连接出现error node【1045】

    第一步:在my.ini下找到mysqlid.在后边添加skip-grant-tables 第二步:重新启动mysql服务 第三步:重新设置密码 第四步: 将skip-grant-tables删除掉,保 ...

  9. 图片文字滚动插件jQuery Scrollbox

    图片文字滚动插件jQuery Scrollbox附件中提供了五种图片.文字滚动样式,只需调用jquery库和jQuery Scrollbox插件,然后再加一段简单的jquery代码即可使用,兼容性良好 ...

  10. 第九课: - 导出到CSV / EXCEL / TXT

    第 9 课 将数据从microdost sql数据库导出到cvs,excel和txt文件. In [1]: # Import libraries import pandas as pd import ...