2009-12-17 11 views
34
for (String fruit : list) 
    { 
     if("banane".equals(fruit)) 
      list.remove(fruit); 
     System.out.println(fruit); 
    } 

Tutaj pętla z instrukcją usuwania. w czasie wykonywania, ja trochę ConcurrentModificationException, poniżej wyjścia konsoli:pętla na liście z usunięciem

Exception in thread "main" java.util.ConcurrentModificationException 
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449) 
at java.util.AbstractList$Itr.next(AbstractList.java:420) 
at Boucle.main(Boucle.java:14) 
abricot 
banane 

pytanie: Jak usunąć jakiś element z pętli?

Odpowiedz

76

Musisz użyć iteratora bezpośrednio i usunąć element przez ten iterator.

for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) { 
    String fruit = iterator.next(); 
    if ("banane".equals(fruit)) { 
     iterator.remove(); 
    } 
    System.out.println(fruit); 
} 
+0

Dla kogoś, kto rozpozna siebie: Nie stosować do przyrostowego z indeksu i list.size() !! Chciałem zmienić kod za pomocą pętli foreach i nie było to poprawne rozwiązanie. Twoja jest ta. – enguerran

+1

wystarczy zmienić 'it.hasNext()' na 'iterator.hasNext()' i jest idealny! (oczywiste ... ale kto wie ...) –

4

Użyj pętli for i zapętlić kolekcję w odwrotnej kolejności. (Oznacza to, że zacznij od ostatniego elementu i zapętlaj do pierwszego elementu.) W ten sposób nie będziesz miał problemów z indeksami, które zmieniają się z powodu usuwania elementów z kolekcji. przykład, że piszesz, bo lista, na której twoi iteracje iteracyjnej, uległa zmianie, co oznacza, że ​​iterator staje się nieważny.

+0

brzmi niebezpiecznie. Co powiesz na listę podwójnie powiązaną i tym podobne, gdzie pamięć nie jest ciągła? Nie wiem, czy lists et al ma 'index' w Javie, czy jak' iterator' jest zaimplementowany, ale jeśli jest podobny do C++, byłbym zaskoczony, gdyby twoje podejście działało z czymkolwiek poza 'ArrayList'. –

4
for(Iterator<String> iter = list.iterator(); iter.hasNext();) 
{ 
    String fruit = iter.next(); 
    if("banana".equals(fruit)) 
     iter.remove(); 
    System.out.println(fruit); 
} 
6

Poza pomocą Iterator bezpośrednio (co polecam) można również sklep elementy, które chcesz usunąć na innej liście.

List<String> toRemove = new ArrayList<String>(); 
for (String fruit : list) { 
    if ("banane".equals(fruit)) 
     toRemove.add(fruit); 
    System.out.println(fruit); 
} 
for (String fruit : toRemove) { 
    list.remove(fruit); 
} 

Pamiętaj, nie polecam tego, to tylko alternatywa. :)

+1

Twoje rozwiązanie jest zbyt szczegółowe. – enguerran

+2

Tak, jest. Dlatego użyłbym rozwiązania opartego na Iteratorze, które napisałem. – Bombe

+0

Istnieje więcej niż jeden sposób, aby to zrobić, ale większość z tych sposobów jest błędna;) – Jorn

1

Podobne do sugestii Bombe, ale w mniej wierszy kodu przez iterowanie na liście kopii, ale usunięcie z oryginalnej listy;

List<String> temp = new ArrayList<String>(list); 
for (String fruit : temp) 
{ 
    if("banane".equals(fruit)) 
     list.remove(fruit); 
    System.out.println(fruit); 
} 

Osobiście uważam, że wygląda ładniej niż iteracja z iteratorem.

+0

Myślę, że łatwiej jest przeczytać – enguerran

+0

Powiedziałbym, że to jest podatne na błędy .. mając 2 listy gdzie nie potrzebujemy drugiego. Tylko moje 2 centy. – cheekoo

+0

@cheekoo, widzę, jak użyłaby niepotrzebnej pamięci, ale nie widzę, jak kompetentny programista wprowadziłby błędy przy użyciu tej metody. –

10

Wydaje się to nieco skomplikowane, dlaczego nie po prostu zrobić zwykłą pętlę? Wydaje mi się, że wygląda na czystsze i nie rzuci tego błędu. Po prostu odrzuć i jeśli coś usuniesz. przynajmniej moje prace. Te rodzaje automatycznych pętli są bardziej wygodne dla kodowania, pomyślałem, więc jeśli nie są wygodne, to po prostu ich nie używaj.

for (int i = list.size() - 1; i>=0; i--) { 
    String fruit = list.get(i); 
    System.out.println(fruit); 

    if ("banane".equals(fruit)) { 
     list.remove(fruit); 
    } 
} 
1
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); 
Iterator<String> iter = list.iterator(); 
while (iter.hasNext()) { 
    String s = iter.next(); 

    if (s.equals("a")) { 
     iter.remove(); 
    } 
} 

jest najlepszym rozwiązaniem ..