2013-06-06 6 views
17

ich, ob würde versuchen, aus der Sammlung zu entfernen, durch sie mit der einfachen Schleife Schleife werde ich diese Ausnahme bekommen: java.util.ConcurrentModificationException. Aber ich benutze Iterator und es erzeugt immer noch diese Ausnahme. Irgendeine Idee warum und wie man es löst?java.util.ConcurrentModificationException mit Iterator

HashSet<TableRecord> tableRecords = new HashSet<>(); 

... 

    for (Iterator<TableRecord> iterator = tableRecords.iterator(); iterator.hasNext();) { 
     TableRecord record = iterator.next(); 
     if (record.getDependency() == null) { 
      for (Iterator<TableRecord> dependencyIt = tableRecords.iterator(); dependencyIt.hasNext();) { 
       TableRecord dependency = dependencyIt.next(); //Here is the line which throws this exception 
       if (dependency.getDependency() != null && dependency.getDependency().getId().equals(record.getId())) { 
        iterator.remove(); 
       } 
      } 
     } 
    } 

Antwort

27

müssen Sie iterator.remove() anstelle von tableRecords.remove()

Sie können Elemente auf einer Liste entfernen, auf dem Sie nur durchlaufen, wenn Sie die Methode remove aus dem Iterator verwenden.

EDIT:

Wenn Sie einen Iterator erstellen, es beginnt die Änderungen zu zählen, die auf die Sammlung angewendet wurden. Wenn der Iterator erkennt, dass einige Änderungen vorgenommen wurden, ohne seine Methode zu verwenden (oder einen anderen Iterator für die gleiche Sammlung verwenden), kann er nicht mehr garantieren, dass er nicht zweimal am selben Element übergeben wird oder überspringt. Daher gibt er die Ausnahme

aus

Es bedeutet, dass Sie Ihren Code ändern müssen, so dass Sie nur Einzelteile über iterator.remove entfernen (und mit nur einem Iterator)

OR

eine Liste der Elemente zu machen, sie zu entfernen, dann entfernen, nachdem Sie Iterieren fertig .

+0

Es gibt zwei verschachtelte Iteratoren so wird es wahrscheinlich nicht das Problem lösen. – assylias

+2

Immer noch das Gleiche. – user2219247

+0

@assylias Das stimmt, ich habe den zweiten nicht gesehen. Ich habe eine Erklärung zu dieser Ausnahme hinzugefügt. –

0

Der Vertrag für Iterator HashSet ist, dass Sie nicht aus der Hashset anders als durch das, spcific Iterators entfernen Methode entfernen können. Aus der Perspektive der dependencyIt haben Sie ein anderes Element als durch den Aufruf seiner remove Methode entfernt, so dass es eine ConcurrentModificationException wirft.

Es scheint, dass Sie Datensätze aus Ihrem Hashset entfernen möchten, wenn sie denselben Datensatz-ID haben. Wäre es nicht einfacher sein, Ihre Aufzeichnungen equals und hashcode Methoden außer Kraft zu setzen, um sicherzustellen, dass die Datensätze mit der gleichen ID gleich und hat den gleichen Hash-Code? (Wenn das Sinn macht natürlich)

0

Das Problem ist, dass Sie zwei Iteratoren gleichzeitig im Bereich haben und sie "kämpfen" miteinander. Der einfachste Weg, um das Problem zu beheben, ist gerade aus der inneren Schleife der Klemme zu helfen, wenn Sie ein Spiel finden:

for (Iterator<TableRecord> iterator = tableRecords.iterator(); iterator.hasNext();) { 
    TableRecord record = iterator.next(); 
    if (record.getDependency() == null) { 
     for (Iterator<TableRecord> dependencyIt = tableRecords.iterator(); dependencyIt.hasNext();) { 
      TableRecord dependency = dependencyIt.next(); //Here is the line which throws this exception 
      if (dependency.getDependency() != null && dependency.getDependency().getId().equals(record.getId())) { 
       iterator.remove(); 
       break; // ADD THIS LINE 
      } 
     } 
    } 
} 

Java Iterator s soll „schnell scheitern“, wenn der zugrunde liegender Behälter ohne geändert wird nachdem geändert mit die Iterator. Sie verwenden verschachtelte Iteratoren, so dass jede Operation, die auf remove() ausgegeben wird, dazu führt, dass die andere Exception auslöst, wenn sie weiterhin verwendet wird. Aus diesem Grund müssen Sie, wenn Sie eine remove() ausgeben müssen, dies auf dem "äußeren" Iterator tun (was Sie tun) und die Verwendung des zweiten Iterators danach einstellen (was die hinzugefügte break-Anweisung tut).

1

Iterator Ausfall schnell Eigenschaft prüft, ob jede Änderung in der Struktur der zugrunde liegenden Auflistung jedes Mal versuchen wir, das nächste Element zu erhalten. Wenn Änderungen gefunden werden, wird ConcurrentModificationException ausgelöst. Alle Implementierungen von Iterator in Sammlung Klassen sind ausfall schnell durch Design mit Ausnahme der gleichzeitigen Collection-Klassen wie ConcurrentHashMap und CopyOnWriteArrayList.

Quelle: Google

Sie werden besser mit einem Beispiel verstehen unten geschrieben: -

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Iterator; 
import java.util.List; 

public class IteratorExp { 
    public static void main(String... q) { 
     //CASE - ONE 
     List<String> strList = new ArrayList<>(Arrays.asList("a", "b", "c")); 
     Iterator<String> itr = strList.iterator(); 
     /* 
     * strList.add("e"); strList.add("f"); strList.add("g"); 
     */ 
     while (itr.hasNext()) { 
      System.out.println(itr.next()); 
     } 
     /* 
     * Exception in thread "main" java.util.ConcurrentModificationException 
     * at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at 
     * java.util.ArrayList$Itr.next(Unknown Source) at 
     * IteratorExp.main(IteratorExp.java:14) 
     */ 

     //CASE - TWO 
     List<Integer> intList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0)); 
     Iterator<Integer> itrOne = intList.iterator(); 
     Iterator<Integer> itrTwo = intList.iterator(); 
     for (; itrOne.hasNext();) { 
      if (itrOne.next().equals(5)) { 
       itrOne.remove(); // #1 
       //intList.remove(itrOne.next()); // #2 
      } 
     } 
     for (; itrTwo.hasNext();) { 
      if (itrTwo.next().equals(5)) { 
       itrTwo.remove(); // #1 
       //intList.remove(itrTwo.next()); // #2 
      } 
     } 

     /* 
     * Exception in thread "main" java.util.ConcurrentModificationException 
     * at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at 
     * java.util.ArrayList$Itr.next(Unknown Source) at 
     * IteratorExp.main(IteratorExp.java:35) 
     */ 
    } 
}