2016-05-13 10 views
0

Wenn ich die Zeile list.add ("3") auskommentiert, wird ConcurrentModificationException ausgelöst. Für zwei Elemente funktioniert es gut und für 1 oder 3 Elemente wird eine Ausnahme geworfen? Irgendeine Erklärung für dieses Verhalten?Inkonsistenz bei gleichzeitiger Änderung der Ausnahmebedingung

import java.util.*; 

public class ConException { 

    public static void main(String[] args) { 
     List<String> list = new ArrayList<String>(); 
     list.add("1"); 
     list.add("2"); 
     //list.add("3"); 
     for(String x: list){ 
      list.remove("1"); 
     } 
     System.out.println(list); 
    } 
} 
+0

wenn Sie entfernen möchten, entfernen Sie durch using index dh list.remove (list.indexOf (0); – emotionlessbananas

+0

@holidayCoder Das wird auch in diesem Szenario nicht funktionieren. – Kayaman

+1

@ user6328922 Überprüfen Sie diesen Link - http://www.journaldev.com/378/how- to-avoid-concurrentmodificationexception-wenn-mit-einem-iterator – Gandhi

Antwort

0

Sie können die Liste nicht ändern, während Sie sie durchlaufen.
So können Sie list.remove("1") innerhalb for (String x: list) Schleife nicht aufrufen.
Schleife entfernen und einfach "1" Element entfernen.

Wenn Sie alle "1" Elemente entfernen Sie dies durch die folgenden Möglichkeiten:

while (list.remove("1")) {} 

EDIT:
Hier dekompilierten wird Code von ArrayListIterator Klasse, die verwendet wird, in for-Schleifen . Nach jeder Iteration next Methode aufgerufen wird, kann in den ConcurrentModificationException

private class ArrayListIterator implements Iterator<E> { 
    /** Number of elements remaining in this iteration */ 
    private int remaining = size; 

    /** Index of element that remove() would remove, or -1 if no such elt */ 
    private int removalIndex = -1; 

    /** The expected modCount value */ 
    private int expectedModCount = modCount; 

    public boolean hasNext() { 
     return remaining != 0; 
    } 

    @SuppressWarnings("unchecked") public E next() { 
     ArrayList<E> ourList = ArrayList.this; 
     int rem = remaining; 
     if (ourList.modCount != expectedModCount) { 
      throw new ConcurrentModificationException(); 
     } 
     if (rem == 0) { 
      throw new NoSuchElementException(); 
     } 
     remaining = rem - 1; 
     return (E) ourList.array[removalIndex = ourList.size - rem]; 
    } 

    public void remove() { 
     Object[] a = array; 
     int removalIdx = removalIndex; 
     if (modCount != expectedModCount) { 
      throw new ConcurrentModificationException(); 
     } 
     if (removalIdx < 0) { 
      throw new IllegalStateException(); 
     } 
     System.arraycopy(a, removalIdx + 1, a, removalIdx, remaining); 
     a[--size] = null; // Prevent memory leak 
     removalIndex = -1; 
     expectedModCount = ++modCount; 
    } 
} 

Unsere Ausnahme von next Verfahren unter den folgenden Bedingungen ausgelöst wird, geworfen werden:

if (ourList.modCount != expectedModCount) { 
    throw new ConcurrentModificationException(); 
} 

Und unsere modCount Variable wurde mit remove Iteration geändert, so Der nächste next Aufruf wird fehlschlagen.

+0

Wie wäre es mit list.remove (list.ind exOf (0) – emotionlessbananas

+0

@holidayCoder Es gibt viele mögliche Lösungen :) Ihr sollte arbeiten, aber 'list.remove (0)' wird einfacher sein, das erste Element zu löschen. –

+0

Die Frage besteht nicht darin, das erste Element zu löschen. Es geht darum, warum 'ConcurrentModificationException' nicht immer geworfen wird. – Kayaman

0

Bitte lesen Sie die Java-doc von ConcurrentModificationException https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html

In Ihrem Fall, Sie erhalten nicht die einzige Ausnahme, wenn Sie zwei Elemente in Ihrem Arraylist, in allen anderen Fällen Sie eine ConcurrentModificationException bekommen.

Wie die javaDoc feststellt, hängt es von der JRE ab, zu bestimmen, ob eine gleichzeitige Änderung stattfindet, und es ist kein garantierter Weg, diese zu bestimmen, wie es in javadoc klar zum Ausdruck kommt.

Beachten Sie, dass verhaltens schnell ausfallen kann nicht garantiert werden, wie es ist, in der Regel gesprochen, unmöglich, irgendwelche harten Garantien in Gegenwart von unsynchronisierten gleichzeitige Modifikation zu machen

+0

er erhält Array von String, aber entfernen Listenobjekt, nicht den tatsächlichen Punkt zu bekommen – emotionlessbananas

Verwandte Themen