我要把ArrayList中的一些元素移除,但抛出了ConcurrentModificationException异常,下面是代码: 
       /**
 * Removes all students in the specified array list whose grade
 * is less than the specified grade.
 *
 * @param arrayList  an array list of <code>Student</code> objects.
 * @param grade  a grade.
 */
public static void removeGradeLess(
ArrayList<Student>  arrayList,
int  grade)  { /* PLACE YOUR CODE HERE */ /* My code is here. ^_^ */ if (arrayList.size() == 0){ }else{ for (Student s : arrayList){ if (s.getGrade() < grade){ arrayList.remove(s);
}
}
}
}这个是测试程序:
        public boolean testRemoveGradeLess() { setUp(); boolean test = true; try { StudentArrayList.removeGradeLess(emptyArrayList, 100);
test = test && assertTrue("1, testing method removeGradeLess",
emptyArrayList.size() == 0);

StudentArrayList.removeGradeLess(arrayList, 90);
test = test && assertTrue("2, testing method removeGradeLess",
arrayList.size() == 3);
test = test && assertTrue("3, testing method removeGradeLess",
arrayList.get(0) == first);
test = test && assertTrue("4, testing method removeGradeLess",
arrayList.get(1) == second);
test = test && assertTrue("5, testing method removeGradeLess",
arrayList.get(2) == fourth);

StudentArrayList.removeGradeLess(arrayListTwo, 90);
test = test && assertTrue("6, testing method removeGradeLess",
arrayListTwo.size() == 2);
test = test && assertTrue("7, testing method removeGradeLess",
arrayListTwo.get(0) == secondArrayListTwo);
test = test && assertTrue("8, testing method removeGradeLess",
arrayListTwo.get(1) == fifthArrayListTwo);
} catch (Exception e) {
test = fail("9, testing method removeGradeLess: " + e.toString());
} return test;
}结果是:
Testing class StudentArrayList...
** Test failure 9, testing method removeGradeLess: java.util.ConcurrentModificationException请问高手怎么解决啊?

解决方案 »

  1.   

    ConcurrentModificationException 的异常分析
    今日运行一段如下代码 
    List<;Person> pList = ... 
    for(Person person : pList){ 
      if(person.getGender()==Gender.MALE){ 
        pList.remove(person); 
      } 
    } 报出的异常为 java.util.ConcurrentModificationException 异常 
    经查找资料 
    public class ConcurrentModificationExceptionextends RuntimeException 
    当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。  例如,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不明确的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出此异常。执行该操作的迭代器称为快速失败 迭代器,因为迭代器很快就完全失败,而不会冒着在将来某个时间任意发生不确定行为的风险。  注意,此异常不会始终指出对象已经由不同 线程并发修改。如果单线程发出违反对象协定的方法调用序列,则该对象可能抛出此异常。例如,如果线程使用快速失败迭代器在 collection 上迭代时直接修改该 collection,则迭代器将抛出此异常。  注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败操作会尽最大努力抛出 ConcurrentModificationException。因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,正确做法是:ConcurrentModificationException 应该仅用于检测 bug。 
    当使用 fail-fast iterator 对 Collection 或 Map 进行迭代操作过程中尝试直接修改 Collection / Map 的内容时,即使是在单线程下运行, java.util.ConcurrentModificationException 异常也将被抛出。    Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。 
      所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。 
      有意思的是如果你的 Collection / Map 对象实际只有一个元素的时候, ConcurrentModificationException 异常并不会被抛出。这也就是为什么在 javadoc 里面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs. 修改后的代码如下: Iterator<Person> it = pList.iterator(); 
    while(it.hasNext()){ 
      if(it.next().getGender()==Gender.MALE){ 
        it.remove(); 
      } 

      

  2.   

    有注释读代码方便点,呵呵^_^还有就是这里面应该只有main的一个线程吧,怎么会有并发修改呢?这个不甚清楚,还望赐教.
      

  3.   

    你在访问一个ArrayList的时候,如果对他再进行移除的话,肯定回造成并发.你可以另外再弄一个集合,将满足条件的数存入到这个集合.然后再一次用原来的集合把新的集合里面的所有元素移除掉.
      

  4.   

    2楼和4楼说的都对我建议你用叠代器试一下:ArrayList list= new ArrayList();Iterator it=list.iterator();
    while(it.hasNext()){
         if((Student)it.next().getGrade()<Grade){
             it.remove();
         }
    }
      

  5.   


    for   (Student   s   :   arrayList){ if   (s.getGrade()   <   grade){ arrayList.remove(s); 
    } 修改为:
    Student   s = null;for (int i = 0; i < arrayList.size; i++)
    {
      s = arrayList.get(i);
      
      if(s.getGrade()   <   grade)
      { 
        arrayList.remove(i); 
      } 
    }这样写法比较安全