2012-01-11 18 views
11

Ho codice molto semplice:ConcurrentModificationException lanciata da sottolista

List<String> list = new ArrayList<String>(); 
    String a = "a"; 
    String b = "b"; 
    String c = "c"; 
    String d = "d"; 

    list.add(a); 
    list.add(b); 
    list.add(c); 

    List<String> backedList = list.subList(0, 2); 
    list.add(0, d); 
    System.out.println("2b: " + backedList); 

e ottengo un'eccezione ConcurrentModificationException da list.add (0, d). Quindi, in generale, è a causa di sublist(). Sono molto confuso, perché in caso di sottoelenco() la documentazione dice:

La lista restituita è sostenuta da questa lista, i cambiamenti in modo da non strutturali in lista restituita si riflettono in questa lista, e vice-versa.

Potrebbe spiegarmi dove si trova il problema?

+2

Il "catturare" discendente è che l'aggiunta di un elemento di una lista è un ** ** cambiamento strutturale. –

+0

il viceversa in quella frase è fuorviante come si menziona @peter, perché come i documenti (e il tuo codice), spiega in seguito, modificando la lista di backup senza passare attraverso la sottolista si solleva una ConcurrentModificationException –

risposta

12

subList è una semplice visualizzazione dell'elenco originale (vedere here). Hai il permesso di modificare gli elementi al suo interno ma non modificare la struttura dell'elenco.

Secondo la documentazione, il comportamento di subList non è definito se si tenta di apportare modifiche strutturali. Immagino che in questa particolare implementazione, ConcurrentModificationException sia stato deciso come comportamento indefinito.

La semantica della lista restituita da questo metodo diventa indefinita se la lista di accompagnamento (cioè, questa lista) è strutturalmente modificata in un modo diverso dall'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.)

+0

ho sprecato un giorno per controllare cosa esattamente andato storto, grazie questo mi ha aiutato a riorganizzare la linea nel mio codice –

+0

Si prega di consultare la risposta ho aggiunto di seguito per ulteriori chiarimenti del commento di cui sopra –

0

list.add (0, d) coinvolge spostando tutti gli elementi di una posizione e la dimensione della lista crescente. È un cambiamento piuttosto strutturale.

3

Questa lista è sostenuta da questa lista, così non strutturali cambiamenti nella lista restituita si riflettono in questa lista, e viceversa. Reference Link

Sopra affermazione è assolutamente corretto, ma dobbiamo tenere a mente cambiamento non strutturali. Vorrei descrivere due esempi che giustificano l'affermazione precedente.
Esempio-1: Esecuzione Non strutturale modifica lista.

public static void main(String[] args) { 
     List<String> listArr = new ArrayList<>(); 
     listArr.add("Delhi"); 
     listArr.add("Bangalore"); 
     listArr.add("New York"); 
     listArr.add("London"); 

     List<String> listArrSub = listArr.subList(1, 3); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 

     //Performing Non-Structural Change in list. 
     Collections.swap(listArr, 0, 1); 

     System.out.println("\nAfter Non-Structural Change...\n"); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 
    } 

output-:

List-: [Delhi, Bangalore, New York, London] 
Sub List-: [Bangalore, New York] 

After Non-Structural Change... 

List-: [Bangalore, Delhi, New York, London] 
Sub List-: [Delhi, New York] 

Explanation-: Come da dichiarazione suddetta documentazione di Oracle, il funzionamento scambiando si riflette in entrambe le liste.

Esempio-2: Esecuzione non strutturali cambiamento sub lista.

public static void main(String[] args) { 
     List<String> listArr = new ArrayList<>(); 
     listArr.add("Delhi"); 
     listArr.add("Bangalore"); 
     listArr.add("New York"); 
     listArr.add("London"); 

     List<String> listArrSub = listArr.subList(1, 3); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 

     //Performing Non-Structural Change in sub list. 
     Collections.swap(listArrSub, 0, 1); 

     System.out.println("\nAfter Non-Structural Change...\n"); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 
    } 

output-:

List-: [Delhi, Bangalore, New York, London] 
Sub List-: [Bangalore, New York] 

After Non-Structural Change... 

List-: [Delhi, New York, Bangalore, London] 
Sub List-: [New York, Bangalore] 

Explanation-: Come da dichiarazione suddetta documentazione di Oracle, il funzionamento scambiando si riflette in entrambe le liste tuttavia è stato eseguito nella lista sotto.

Come abbiamo visto le variazioni non strutturali nei suddetti due esempi. Vediamo ora le modifiche Structural come di seguito riportato nella documentazione di Oracle.

La semantica della lista restituita da questo metodo diventa indefinita se la lista di accompagnamento (cioè, questa lista) è strutturalmente modificata in un modo diverso dall'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.)

Esempio-3: Performing strutturali variazione lista .

public static void main(String[] args) { 
     List<String> listArr = new ArrayList<>(); 
     listArr.add("Delhi"); 
     listArr.add("Bangalore"); 
     listArr.add("New York"); 
     listArr.add("London"); 

     List<String> listArrSub = listArr.subList(1, 3); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 

     //Performing Structural Change in list. 
     listArr.add("Mumbai"); 

     System.out.println("\nAfter Structural Change...\n"); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 
    } 

output-:

List-: [Delhi, Bangalore, New York, London] 
Sub List-: [Bangalore, New York] 

After Structural Change... 

List-: [Delhi, Bangalore, New York, London, Mumbai] 
Exception in thread "main" java.util.ConcurrentModificationException 
    at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1231) 
    at java.util.ArrayList$SubList.listIterator(ArrayList.java:1091) 
    at java.util.AbstractList.listIterator(AbstractList.java:299) 
    at java.util.ArrayList$SubList.iterator(ArrayList.java:1087) 
    at java.util.AbstractCollection.toString(AbstractCollection.java:454) 
    at java.lang.String.valueOf(String.java:2982) 
    at java.lang.StringBuilder.append(StringBuilder.java:131) 
    at infosys.Research.main(Research.java:26) 

Explanation-: Secondo suddetta dichiarazione documentazione Oracle, operazione di modifica strutturale è gettare java.util.ConcurrentModificationException eccezione ogniqualvolta La semantica della lista restituita da questo metodo diventa indefinito se il supporto lista (cioè, questa lista) è strutturalmente modificata in un modo diverso dall'elenco restituito.

Esempio-4: Esecuzione strutturale cambiamento sub lista.

public static void main(String[] args) { 
     List<String> listArr = new ArrayList<>(); 
     listArr.add("Delhi"); 
     listArr.add("Bangalore"); 
     listArr.add("New York"); 
     listArr.add("London"); 

     List<String> listArrSub = listArr.subList(1, 3); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 

     //Performing Structural Change in sub list. 
     listArrSub.add("Mumbai"); 

     System.out.println("\nAfter Structural Change...\n"); 

     System.out.println("List-: " + listArr); 
     System.out.println("Sub List-: " + listArrSub); 
    } 

output-:

List-: [Delhi, Bangalore, New York, London] 
Sub List-: [Bangalore, New York] 

After Structural Change... 

List-: [Delhi, Bangalore, New York, Mumbai, London] 
Sub List-: [Bangalore, New York, Mumbai] 

Explanation-: modifica strutturale all'elenco restituito funziona bene e riflettendo nell'elenco del tutto.

0

scenario in cui è stato rilevato questo errore

  • ho avuto una lista (lista originale) con diciamo 100 articolo
  • Ordina lista originale in ordine crescente
  • sottolista esso -> sottolista creato (sottolista ordinato crescente)
  • Ordina l'elenco originale in ordine decrescente
  • Elenco iterato su sottolista (ordine crescente sottordinato)

eccezione Got modifica simultanea

Fix sopra scenario

  • ho avuto una lista (lista originale) con diciamo 100 articolo
  • Ordina in ordine crescente
  • Sottolista it -> creato sottolista (sottolista ordinato crescente)
  • iterare sublisted (ascendente ordinato sublist) Lista
  • ordine elenco originale per
Problemi correlati