2013-07-27 13 views
7

Dlaczego następujący kod rzuca ConcurrentModificationExcrption, kiedy wyczyściłem podlistę po głównej liście, ale nie, jeśli wyczyściłem podlistę, a następnie listę główną?ConcurrentModificationException podczas usuwania listy podrzędnej

ArrayList<Integer> masterList = new ArrayList<Integer>(); 
List<Integer> subList; 

// Add some values to the masterList 
for (int i = 0; i < 10; i++) { 
    masterList.add(i * i); 
} 

// Extract a subList from the masterList 
subList = masterList.subList(5, masterList.size() - 1); 

// The below throws ConcurrentModificationException 
masterList.clear(); 
subList.clear(); // Exception thrown in this line 

// The below doesn't throw any exception 
subList.clear(); 
masterList.clear(); // No exception thrown. Confused?? 

Odpowiedz

4

SubList nie jest niezależną jednostką, ale po prostu przedstawia widok oryginalnej listy i wewnętrznie odnosi się do tej samej listy. W związku z tym wydaje się, że jego konstrukcja jest taka, że ​​jeśli podstawowa lista jest zmodyfikowana strukturalnie (dodanie/usunięcie elementów), nie jest w stanie wypełnić swojej umowy.

Jak widać here in the source code of SubList, sposób checkForComodification sprawdza, czy lista Bazowego zostały zmodyfikowane, a tym samym czy modCount (liczba razy lista została zmodyfikowana strukturalnie) wartości SubList nie jest taki sam jak rodzica ArrayList zatem rzuca ConcurrentModificationException

Więc, rozliczeń rodzica ArrayList z którego został utworzony SubList może spowodować w niektórych operacji SubList spowodować ConcurrentModificationException

+0

To jest bardzo pouczające. Dziękuję Ci. –

2

subList jest widok na masterList. Jest tylko jedna podstawowa kolekcja. Teraz masterList jest rodzajem podlisty superset. Więc

  • sublist nie może istnieć, jeśli masterlist's elementy są usuwane // przypadek wyjątek
  • masterlist może istnieć, jeśli sublist's elementy są usuwane // OK
+0

Czy to tak podlistę odnosi się do elementów Główny wykaz A nd kiedy robię masterList.clear(), referencje ulegają zniszczeniu, a subList.clear() zgłasza wyjątek? –

2

acording do ArrayList docsubList() zwraca podmenu, który jest wspierany przez oryginalną tablicę ArrayList, więc jeśli oryginalny zmienia się tak, to podlista, gdy wykonasz subList.clear() sama podlista już nie istnieje.

2

Z the API docs:

Semantyki liście uzyskanej tym sposobem stać zdefiniowana, gdy lista podkład (czyli ta lista) jest strukturalnie zmodyfikowany w inny sposób niż za pomocą zwróconej listy. (Modyfikacje strukturalne są te, które zmieniają wielkość tej listy, albo w inny sposób zakłócać w taki sposób, że iteracje w toku mogących dawać błędne wyniki.)

niezdefiniowany semantyka oznacza oczywiście to, że dopuszcza się wyjątek, (i rzeczywiście jest to prawdopodobnie najmądrzejszy sposób działania).

Możesz zmienić rozmiar podlisty i odzwierciedlić te zmiany na głównej liście, ale odwrócenie nie jest prawdą.

Powiązane problemy