list删除操作 java.util.ConcurrentModificationException

首先大家先看一段代码:

public static void main(String[] args) {

List<String> listStr = new ArrayList<String>();
      listStr.add("1");
      listStr.add("2");
      listStr.add("3");
      listStr.add("4");
      listStr.add("5");

System.out.println("listStr.size:::"+listStr.size());

for(String str:listStr){
         if("3".equals(str)){
             listStr.remove(str);

}
      }

System.out.println("listStr.size:::"+listStr.size());

现象:

该程序会抛出一个  java.util.ConcurrentModificationException异常。

分析:

对 Collection 或 Map 进行迭代操作过程中尝试直接修改 Collection / Map 的内容时,会抛出java.util.ConcurrentModificationException 异常。 因为在修改数据时不能同步原有list中数据,当下一次循环时找不到数据。

解决办法:

Iterator 在工作的时候是不允许被迭代的对象被改变的,使用 Iterator 本身的方法 remove() 来删除对 
象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。

改后代码:

public static void main(String[] args) {

List<String> listStr = new ArrayList<String>();
      listStr.add("1");
      listStr.add("2");
      listStr.add("3");
      listStr.add("4");
      listStr.add("5");

System.out.println("listStr.size:::"+listStr.size());

Iterator<String> ite = listStr.iterator();
      while(ite.hasNext()){
          String str = (String)ite.next();
          if("3".equals(str)){
             ite.remove();
          }
      }

System.out.println("listStr.size:::"+listStr.size());

}

补充:

或许有人可能会问如果我不用增强for循环,直接用.get(index)方法会不会报错?

代码如下:

for(int i = 0 ; i < listStr.size(); i++){
           if("3".equals(listStr.get(i))){
               listStr.remove(i);
           }
      }

现象:

listStr.size:::5
        listStr.size:::4

大家可以看到通过list的下表索引来修改list数据是不会出错的。

分析:

大家可以这样认为:通过所引来循环时,jvm记录的是所引值,当移除当前对象后,其他元素的索引号不会同步改变。下次循环仍可以找到对应数据。而增强for循环,记录的是当前对象,当下次循环时,会先找到该对象,然后游标向下移,这时候找不到对象所以结果会混乱。

java.util.ConcurrentModificationException

【引言】

经常在迭代集合元素时,会想对集合做修改(add/remove)操作,类似下面这段代码:

[java] view plaincopy

  1. for (Iterator<Integer> it = list.iterator(); it.hasNext(); ) {
  2. Integer val = it.next();
  3. if (val == 5) {
  4. list.remove(val);
  5. }
  6. }

运行这段代码,会抛出异常java.util.ConcurrentModificationException。

【解惑】

(以ArrayList来讲解)在ArrayList中,它的修改操作(add/remove)都会对modCount这个字段+1,modCount可以看作一个版本号,每次集合中的元素被修改后,都会+1(即使溢出)。接下来再看看AbsrtactList中iteraor方法

[java] view plaincopy

  1. public Iterator<E> iterator() {
  2. return new Itr();
  3. }

它返回一个内部类,这个类实现了iterator接口,代码如下:

[java] view plaincopy

  1. private class Itr implements Iterator<E> {
  2. int cursor = 0;
  3. int lastRet = -1;
  4. int expectedModCount = modCount;
  5. public boolean hasNext() {
  6. return cursor != size();
  7. }
  8. public E next() {
  9. checkForComodification();
  10. try {
  11. E next = get(cursor);
  12. lastRet = cursor++;
  13. return next;
  14. } catch (IndexOutOfBoundsException e) {
  15. checkForComodification();
  16. throw new NoSuchElementException();
  17. }
  18. }
  19. public void remove() {
  20. if (lastRet == -1)
  21. throw new IllegalStateException();
  22. checkForComodification();
  23. try {
  24. AbstractList.this.remove(lastRet);
  25. if (lastRet < cursor)
  26. cursor--;
  27. lastRet = -1;
  28. // 修改expectedModCount 的值
  29. expectedModCount = modCount;
  30. } catch (IndexOutOfBoundsException e) {
  31. throw new ConcurrentModificationException();
  32. }
  33. }
  34. final void checkForComodification() {
  35. if (modCount != expectedModCount)
  36. throw new ConcurrentModificationException();
  37. }
  38. }

在内部类Itr中,有一个字段expectedModCount ,初始化时等于modCount,即当我们调用list.iterator()返回迭代器时,该字段被初始化为等于modCount。在类Itr中next/remove方法都有调用checkForComodification()方法,在该方法中检测modCount == expectedModCount,如果不相当则抛出异常ConcurrentModificationException。

前面说过,在集合的修改操作(add/remove)中,都对modCount进行了+1。
在看看刚开始提出的那段代码,在迭代过程中,执行list.remove(val),使得modCount+1,当下一次循环时,执行 it.next(),checkForComodification方法发现modCount != expectedModCount,则抛出异常。

【解决办法】
如果想要在迭代的过程中,执行删除元素操作怎么办?
再来看看内部类Itr的remove()方法,在删除元素后,有这么一句expectedModCount = modCount,同步修改expectedModCount 的值。所以,如果需要在使用迭代器迭代时,删除元素,可以使用迭代器提供的remove方法。对于add操作,则在整个迭代器迭代过程中是不允许的。 其他集合(Map/Set)使用迭代器迭代也是一样。

    //获奖显示
    public String prizeList(){
        voteList = userWorksService.getAllRank();
        UserWorks userWorks = new UserWorks();
        Iterator<UserWorks> list = voteList.iterator();
        Integer rank ;
        while(list.hasNext()){
            userWorks = list.next();
            if(!("9".equals(userWorks.getAwardsRank()))){
                rank = Integer.parseInt(userWorks.getAwardsRank())+2;
                userWorks.setAwardsRank(rank +"");
                allList.add(userWorks);
            }
        }
        voteList.removeAll(allList);
        return "prizeList";
    }
时间: 2024-11-06 03:40:23

list删除操作 java.util.ConcurrentModificationException的相关文章

Hashtable 删除元素, 抛出异常 java.util.ConcurrentModificationException

今天在对一个Hashtable对象进行 搜索 -> 删除 操作时遇到的一个问题,开始的使用我使用的是Hashtable的Iterator,然后直接执行: Hashtable.remove(key); 抛出异常  java.util.ConcurrentModificationException 查了一下java api doc,相关介绍如下: 由迭代器返回的 Iterator 和由所有 Hashtable 的“collection 视图方法”返回的 Collection 的 listIterat

集合循环删除问题-报错java.util.ConcurrentModificationException解析

java.util.ConcurrentModificationException 异常问题详解 环境:JDK 1.8.0_111 在Java开发过程中,使用iterator遍历集合的同时对集合进行修改就会出现java.util.ConcurrentModificationException异常,本文就以ArrayList为例去理解和解决这种异常. 一.单线程情况下问题分析及解决方案 1.1 问题复现 先上一段抛异常的代码. 1 public void test1() { 2 ArrayList

SpringMvc中Hashmap操作遇到 java.util.ConcurrentModificationException: null

代码按照网上修改为类似,还不能解决问题 for (Iterator<String> it = target.keySet().iterator(); it.hasNext(); ) { if(...) it.remove(); } ,后来根据异常名称,推测是在Servlet多线程环境下保持,换成并发ConcurrentHashMap就解决问题了. 参考: HashMap报错:java.util.ConcurrentModificationException 原文地址:https://www.c

java集合--java.util.ConcurrentModificationException异常

ConcurrentModificationException 异常:并发修改异常,当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常.一个线程对collection集合迭代,另一个线程对Collection进行修改的时候, 就会出现上面的异常. 下面看一下代码: package cn.itcast.p4.list.demo; import java.util.ArrayList; import java.util.Iterator; import java.util.List; pub

java.util.ConcurrentModificationException异常分析

Java在操作ArrayList.HashMap.TreeMap等容器类时,遇到了java.util.ConcurrentModificationException异常.以ArrayList为例,如下面的代码片段: [java] view plaincopy import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.CopyOnWriteArr

java.util.ConcurrentModificationException 异常解决办法及原理

最近在修程序的bug,发现后台抛出以下异常: Exception in thread "main" java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793) at java.util.HashMap$KeyIterator.next(HashMap.java:828) at com.keyman.demo.test.ClearResult

java.util.ConcurrentModificationException的解决办法

今天在使用iterator.hasNext()操作迭代器的时候,当迭代的对象发生改变,比如插入了新数据,或者有数据被删除. 编译器报出了以下异常: Exception in thread "main" java.util.ConcurrentModificationException at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:719) at java.util.LinkedHash

android详细信息java.util.ConcurrentModificationException变态

在今天做android当项目,我遇到了这个异常,好吧.其实最不寻常遇到异常IllegalstateException.它们与我们的硬件连接SDK抛出,我想折磨学生阿玉啊.扯远了. 今天,我想回到这个异常.java.util.ConcurrentModificationException异常,一開始我愣了一下.貌似从来没遇到过这个,然后果断百度大神.这才发现: 原因是你遍历该集合时.对该集合进行了删除元素的操作导致的.假设你有删除元素的必要,建议赋值到还有一个集合,然后对他进行删除操作. 偶出现错

小小异常:java.util.ConcurrentModificationException

1 public static void main(String[] args) { 2 ArrayList<String> list = new ArrayList<String>(); 3 for(int i = 0; i < 5; i++){ 4 list.add("str"+i); 5 } 6 for(String item:list){ 7 if("str2".equals(item)){ 8 list.remove(&quo