2014-05-07 11 views
6

Ho letto un articolo riguardante la rimozione di elementi provenienti da collezioni da this linkcollezioni sopprimere metodo non dà Modifica concomitante Eccezione

Come per la mia comprensione metodo iterator remove impedisce eccezione modifica simultanea quindi rimuovere il metodo di Collection.But quando provo per eseguire il Codde di seguito non sono in grado di ottenere concurrentmoficationexception

 List dayList= new ArrayList(); 
    dayList.add("Sunday"); 
    dayList.add("Monday"); 
    dayList.add("Tuesday"); 
    dayList.add("Wednesday"); 
    dayList.remove("Tuesday"); 
    Iterator itr=dayList.iterator(); 
     while(itr.hasNext()) 
     { 
      Object testList=itr.next(); 
      if(testList.equals("Monday")) 
      { 
      dayList.remove(testList); 

      } 
    } 
    System.out.println(dayList); 
} 
  • Come per javadoc il ConcurrentModicationException viene generata quando cerchiamo di fare alcuna modifica durante iteartion.I sto usando colle ctions rimuove il metodo, ma ancora non ci sono eccezioni. Ma se commento la riga dayList.remove ("Tuesday");, viene generata un'eccezione.

Qualcuno può spiegare cosa sta succedendo dietro la scena in questo codice?

+0

La descrizione non è esatta. Ottieni l'eccezione solo se elimini entrambe le righe. – EJP

+0

Consultare la documentazione ConcurrentModificationException: http://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html –

+0

@EJP Anche se mantiene la riga 'iterator.remove()' commentata , riceverà comunque l'eccezione chiamando di nuovo 'iterator.next()'. –

risposta

1

se io commento linea dayList.remove ("Martedì") ;, viene generata un'eccezione ....

In realtà questo non è problema qui. Il problema è che si sta verificando un'eccezione solo per il valore medio.

‘per ogni’ opere di loop come segue,

1.It gets the iterator. 
2.Checks for hasNext(). 
public boolean hasNext() 
{ 
     return cursor != size(); // cursor is zero initially. 
} 
3.If true, gets the next element using next(). 

public E next() 
{ 
     checkForComodification(); 
     try { 
     E next = get(cursor); 
     lastRet = cursor++; 
     return next; 
     } catch (IndexOutOfBoundsException e) { 
     checkForComodification(); 
     throw new NoSuchElementException(); 
     } 
} 

final void checkForComodification() 
{ 
    // Initially modCount = expectedModCount (our case 5) 
     if (modCount != expectedModCount) 
     throw new ConcurrentModificationException(); 
} 

Ripete i punti 2 e 3 fino hasNext() restituisce false.

Nel caso in cui rimuoviamo un elemento dall'elenco, la sua dimensione viene ridotta e modCount viene aumentato.

Se rimuoviamo un elemento durante l'iterazione, modCount!= expectedModCount get satisfied e ConcurrentModificationException viene lanciata.

Ma la rimozione del penultimo oggetto è strana. Vediamo come funziona nel tuo caso.

Inizialmente,

cursor = 0 size = 5 --> hasNext() succeeds and next() also succeeds without exception. 
cursor = 1 size = 5 --> hasNext() succeeds and next() also succeeds without exception. 
cursor = 2 size = 5 --> hasNext() succeeds and next() also succeeds without exception. 
cursor = 3 size = 5 --> hasNext() succeeds and next() also succeeds without exception. 

Nel tuo caso, come si rimuove 'D', la dimensione si riduce a 4.

cursor = 4 size = 4 --> hasNext() does not succeed and next() is skipped. 

In altri casi, ConcurrentModificationException sarà gettato come modCount! = ExpectedModCount .

In questo caso, questo controllo non ha luogo.

Se si tenta di stampare l'elemento durante l'iterazione, verranno stampate solo quattro voci. L'ultimo elemento è saltato.

La tua domanda è simile a this domanda.

2

Non è possibile garantire il comportamento di errore di un iteratore. Gli iteratori fail-fast lanciano ConcurrentModificationException su una base best-effort. L'iteratore può o non può rilevare l'utilizzo non valido. Pertanto, sarebbe sbagliato scrivere un programma che dipendesse da questa eccezione per la sua correttezza: il comportamento fail-fast degli iteratori dovrebbe essere usato solo per rilevare i bug.

+0

Mi sarebbe piaciuto avere visto la documentazione specificare che le raccolte dovrebbero sforzarsi di lanciare ConcurrentModificationException nei casi in cui modifiche simultanee renderebbero impossibile per un iteratore garantire un comportamento "sano", ma nei casi in cui una raccolta potrebbe comportarsi in modo corretto non c'era niente di sbagliato nel farlo. – supercat

1

anche aggiungere un Thursday e si dovrebbe iniziare a ricevere di nuovo l'eccezione :)

List dayList= new ArrayList(); 
dayList.add("Sunday"); 
dayList.add("Monday"); 
dayList.add("Tuesday"); 
dayList.add("Wednesday"); 
dayList.add("Thursday"); // Added by Kuldeep 
dayList.remove("Tuesday"); 
Iterator itr=dayList.iterator(); 
while(itr.hasNext()) 
{ 
    Object testList=itr.next(); 
    if(testList.equals("Monday")) 
    { 
     dayList.remove(testList); 
    } 
} 
System.out.println(dayList); 

Quindi, in sostanza, che è perché Il comportamento fail-veloce di un iteratore non può essere garantita. Gli iteratori fail-fast lanciano ConcurrentModificationException su una base best-effort. Guarda lo documentation here.

EDIT: L'eccezione non è gettata nel tuo caso è perché nel codice seguente:

if(testList.equals("Monday")) 
    { 
     dayList.remove(testList); 
    } 

sei rimuovere il secondo elemento ultima, che in realtà modificare le dimensioni o la dayList da a . Quindi itr.hasNext() restituisce false dopo Monday viene rimosso dall'elenco e quindi non entra nel ciclo per l'ultima voce, ovvero Wednesday ed evita la chiamata a itr.next(). Puoi provare a eseguire il debug del codice per verificare questo comportamento.

+0

ConcurrentModificationException viene generato quando l'utente tenta di modificare la raccolta durante l'iterazione, quindi perché il codice non genera eccezioni e come fa dayList.remove ("Tuesday"); fa la differenza ... il codice dentro mentre è sufficiente per lanciare l'inganno – coder25

+0

Ciò è dovuto al fatto che "il comportamento fail-fast non può essere garantito in quanto è, in generale, impossibile dare garanzie rigide in presenza di modifiche simultanee non sincronizzate. Le operazioni a prova di errore generano ConcurrentModificationException su una base ottimale. Leggere la documentazione di ConcurrentModificationException. –

+0

L'ho capito ma dayList.add ("Wednesday"); e dayList.add ("giovedì"); sono fatti prima dell'iterazione, come questo è collegato con l'eccezione e come per il collegamento http://javarevisited.blogspot.in/2014/01/ow-to-remove-objects-from-collection-arraylist-java-iterator-traversing.html , dovrebbe gettare un'eccezione nel mio caso. – coder25

Problemi correlati