Wie kann man in Java Elemente aus einer Liste in einer Schleife entfernen?

Wenn man in einer Schleife Elemente aus einer Liste entfernen möchte, bekommt in der Regel (aber komischerweise nicht immer) die ConcurrentModificationException:

List<String> test = new ArrayList<>(Arrays.asList("Foo", "Bar", "Baz"));

for (String str : test) {
	if (str.equals("Foo")) {
		test.remove(str);
		// ConcurrentModificationException
	}
}

Mit "Bar":

if (str.equals("Bar")) {
		test.remove(str);
		// Läuft durch?!
	}

passiert es aber nicht. Warum?

Noch keine Stimmen abgegeben
Noch keine Kommentare
  • 7 Jul. 2019

    Es geht auch mit normalen for-Schleifen. Mit r√ľckw√§rts Iterieren:

    for (int i = (test.size() - 1); i >=0; i--) {
        if ("Bar".equals(test.get(i))) {
             test.remove(i);
        }
    }
    

    W√§hrend der Iteration √§ndert sich L√§nge des Arrays (von 3 auf 2 in diesem Beispiel). Aber dadurch, dass wir r√ľckw√§rts Iterieren, wir die "size" Methode nur bei der Initialisierung der Z√§hlvariable ben√∂tigt.

    Das Entfernen funktioniert auch beim "normalen"-Iterieren, man muss dann aber immer die Zählvariable anpassen (weil die Schleifen-Bedingung bei jedem Durchlauf evaluiert wird):

    for (int i = 0; i < test.size(); i++) {
        if ("Bar".equals(test.get(i))) {
             test.remove(i);
             i--;
        }     
    }
    
    Noch keine Stimmen abgegeben
    Noch keine Kommentare
  • 7 Jul. 2019

    Dazu gibt es verschiedene Möglichkeiten:

    Mit dem Iterator

    Iterator<String> testIterator = test.iterator();
    while(testIterator.hasNext()) {     
        String t = testIterator.next();     
        if ("Bar".equals(t)) {
            fruitIterator.remove();
        } 
    }
    

    Diese Methode funktioniert aber nicht immer. F√ľr zB. Arrays.asList(...) kommt hier UnsupportedOperationException.

    Am einfachsten funktioniert es mit Streams ab Java 8:

    List<String> ohneBar =  test
        .stream()
        .filter(t -> !"Bar".equals(t))
        .collect(Collectors.toList());
    

    oder mit removeIf ("Bar" und "Baz" aus der Liste entfernt)

    test.removeIf(t -> t.equals("Bar") || t.equals("Baz"))
    
    Noch keine Stimmen abgegeben
    Noch keine Kommentare