添加另一个对象时java.util.ConcurrentModificationException

我正在遭遇这个例外。 我的代码有什么问题? 我只想在另一个ArrayList分离Person的重复名称

 public class GlennTestMain { static ArrayList ps; static ArrayList duplicates; public static void main(String[] args) { ps = new ArrayList(); duplicates = new ArrayList(); noDuplicate(new Person("Glenn", 123)); noDuplicate(new Person("Glenn", 423)); noDuplicate(new Person("Joe", 1423)); // error here System.out.println(ps.size()); System.out.println(duplicates.size()); } public static void noDuplicate(Person p1) { if(ps.size() != 0) { for(Person p : ps) { if(p.name.equals(p1.name)) { duplicates.add(p1); } else { ps.add(p1); } } } else { ps.add(p1); } } static class Person { public Person(String n, int num) { this.name = n; this.age = num; } String name; int age; } } 

这是堆栈跟踪

 Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at java.util.ArrayList$Itr.next(Unknown Source) at hk.com.GlennTestMain.noDuplicate(GlennTestMain.java:41) at hk.com.GlennTestMain.main(GlennTestMain.java:30) 

您无法修改正在迭代的collection 。 这可能会引发ConcurrentModificationException 。 虽然它有时会起作用,但并不能保证每次都能正常工作。

如果要添加或删除列表中的内容,则需要使用IteratorListIterator作为列表。 并使用ListIterator#add方法添加列表中的任何内容。 即使在你的iterator ,如果你尝试使用List.addList.remove ,你也会得到那个例外,因为这没有任何区别。 您应该使用iterator的方法。

请参阅这些post以了解如何使用它: –

  • Java:迭代列表时出现ConcurrentModificationException
  • 迭代集合,在循环中删除时避免ConcurrentModificationException

原因?

ArrayList返回的迭代器本质上是fail-fast

这个类的iterator和listIterator方法返回的迭代器是fail-fas t:如果在创建迭代器后的任何时候对列表进行结构修改,除了通过迭代器自己的remove或add方法之外,迭代器将抛出ConcurrentModificationException 。 因此,在并发修改的情况下,迭代器快速而干净地失败,而不是在未来的未确定时间冒任意,非确定性行为的风险。

当我不使用它时,这个迭代器来自哪里?

对于集合的增强for循环, Iterator会被使用,因此在Iterator时不能调用add方法。

所以你的循环与下面相同

 for (Iterator i = c.iterator(); i.hasNext(); ){ 

什么是解决方案呢?

你可以调用iterator.add(); 并基于迭代器显式而不是隐式地更改循环。

  String inputWord = "john"; ArrayList wordlist = new ArrayList(); wordlist.add("rambo"); wordlist.add("john"); for (ListIterator iterator = wordlist.listIterator(); iterator .hasNext();) { String z = iterator.next(); if (z.equals(inputWord)) { iterator.add("3"); } } System.out.println(wordlist.size()); 

现在哪里可以阅读更多内容?

  1. For-Each循环
  2. ArrayList Java文档

加。 到Java Docs :

如果一个线程在使用失败快速迭代器迭代集合时直接修改集合,则迭代器将抛出此exception。

您在使用Enhanced For循环迭代时添加Person对象。

您可以进行以下修改:

 boolean duplicateFound = false; for(Person p : ps) { if(p.name.equals(p1.name)) { duplicates.add(p1); duplicateFound = true; } } if( ! duplicateFound) { ps.add(p1); }