2013-07-27 17 views
7

Perché il seguente codice genera ConcurrentModificationExcrption, quando si cancella l'Elenco secondario dopo l'Elenco principale, ma non se si cancella l'elenco secondario e quindi l'Elenco principale?ConcurrentModificationException durante la cancellazione di un sottoelenco

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?? 

risposta

4

SubList non è un'entità indipendente, ma fornisce semplicemente una vista dell'elenco originale e fa riferimento internamente alla stessa lista. Quindi, il suo design sembra essere tale che se l'elenco sottostante viene modificato strutturalmente (aggiunta/rimozione di elementi), non è in grado di adempiere al suo contratto.

Come si vede here in the source code of SubList, il metodo checkForComodification verifica se l'elenco sottostante è stato modificato, e quindi se il modCount (numero di volte che l'elenco è stato strutturalmente modificato) valore SubList non è lo stesso come genitore ArrayList, poi, getta ConcurrentModificationException

Quindi, compensazione genitore ArrayList da cui è stato creato SubList può provocare le certe operazioni di SubList di provocare ConcurrentModificationException

+0

Questo è molto informativo. Grazie. –

2

subList è una vista sul masterList. C'è solo 1 collezione di base. Ora masterList è una specie di superset di sottolista. Così,

  • sublist non può esistere se masterlist's elementi vengono rimossi // caso eccezione
  • masterlist può esistere se sublist's elementi vengono rimossi // OK
+0

E 'come la sottolista si riferisce agli elementi di un MasterList Quando faccio masterList.clear(), i riferimenti vengono distrutti e subList.clear() genera un'eccezione? –

2

di tronchi con a ArrayList docsubList() restituisce un elenco secondario che è sostenuta dalla ArrayList originale, quindi se l'originale cambia così fa la sottocartella, quando esegui subList.clear() la stessa sottolista non esiste più.

2

Da the API docs:

La semantica della lista restituita da questo metodo diventare definito se l'elenco di supporto (cioè, l'elenco) è strutturalmente modifica in alcun modo se non attraverso l'elenco restituito. (Modifiche strutturali sono quelli che cambiano le dimensioni di questo elenco, o altrimenti perturbare in modo tale che iterazioni in corso possono produrre risultati errati.)

Definire semantica significa ovviamente che è permesso un'eccezione (e in effetti questo è probabilmente il modo più saggio di agire).

Quindi è possibile modificare la dimensione della sottolista e avere quelle modifiche riflesse nella lista principale, ma il contrario non è vero.

Problemi correlati