2013-05-19 8 views
8

voglio scrivere codice come questo -Come rimuovere e aggiungere elementi a TreeMap durante l'iterazione?

for (Map.Entry<Long, Integer> e : map.entrySet()){ 
    map.remove(k); 
    map.put(x, value); 
} 

ma ho avuto java.util.ConcurrentModificationException Ho provato ad usare Iterator anche, ma ho ottenuto lo stesso Exception

+4

@ZouZou Ho cercato su google per questo e ho trovato questa domanda sul primo posto. Google non è sufficiente, è necessario anche il contenuto :-) – peterh

+0

Puoi allegare il codice per l'iteratore. Il codice sopra fornirà certamente un'eccezione di modifica simultanea. Stai iterando attraverso il keyset e modificando la mappa allo stesso tempo. Questa è una ricetta per il disastro. – SamDJava

+0

Aggiunta una risposta qui sotto con un codice di esempio. – SamDJava

risposta

7

Explaintion perché è causato ConcurrentModificationException

map.remove(k); 
map.put(x, value); 

per ogni ciclo anche creare internamente un iteratore di entrySet di map. Durante l'iterazione sulla mappa, hai modificato la struttura della mappa riportando il valore sulla mappa (map.put(x,value)) che causa questo ConcurrentModificationException.

E 'ancora ben spiegato in documentation -

Gli iteratori restituito da tutti di questa classe "Vista la raccolta metodi" sono fail-fast: se la mappa è strutturalmente modificato in qualsiasi momento dopo l'iteratore viene creato, in qualsiasi modo tranne che attraverso il metodo di rimozione dello stesso iteratore , l'iteratore genererà un valore di ConcurrentModificationException .Pertanto, a fronte della simultanea modifica di , l'iteratore non riesce in modo rapido e pulito, piuttosto che a rischio di comportamento arbitrario non deterministico in un tempo indeterminato in futuro.

Come risolvere questo -

è necessario modificare il cambiamento della struttura di questa mappa, mentre l'iterazione, è possibile inserire questi valori in seguito, come tenere una mappa temporanea e aggiungere questo una volta di iterazione è finito il suo lavoro.

Map<Long, Integer> tempMap = new HashMap<>(); 
for (Map.Entry<Long, Integer> e : map.entrySet()){ 
    map.remove(k); 
    tempMap.put(x, value); 
} 
map.putApp(tempMap); 
1

Si dovrà creare una copia della mappa utilizzando la copia costruttore. Ora esegui l'iterazione su 1 e modifica la seconda mappa. Suppongo che non sarà necessario iterare il nuovo valore aggiunto in quanto non ha molto senso.

È possibile raggiungere il proprio compito creando una copia perché i tasti rimarranno uguali in entrambi.

EDIT:

non penso proprio una buona idea per scorrere l'elemento appena aggiunto ad un HashMap. Se controlli le API fornite da Iterator, troverai solo il metodo di rimozione, non ci sono metodi di aggiunta. C'è una ragione dietro questo e puoi controllare javadoc per questo. Ora arriviamo al punto, su come iterare l'elemento appena aggiunto.

  1. Creare una copia del numero HashMap. Quindi lo si itererà e si modificherà l'altro Map.
  2. Poiché il requisito è quello di aggiungere e rimuovere elementi in Map, vorrei utilizzare ListIterator per questo [questo è diverso dal normale Iterator].
  3. Otterrò il keyset di Map1 e lo convertirò in un elenco utilizzando ArrayList(Collection<? extends E> c).
  4. Ora mi metterò ListIterator da List creata al punto 3, e aggiungere, rimuovere gli elementi in ListIterator così come in Map2 [Ricordate che è necessario aggiungere, rimuovere sia in ListIterator e Map2].
+0

no Ho bisogno di iterare su questi nuovi valori i nuovi valori aggiunti saranno maggiori di quello attuale quindi ho bisogno di iterare su di loro anche –

+0

vedere la mia modifica. Utilizzando i passaggi appena aggiunti è possibile eseguire l'aggiunta e la rimozione di entrambi. – Lokesh

0

Perché non puoi farlo.

Una soluzione semplice è quella di utilizzare un'altra mappa temporanea dove si mettono i valori desiderati e infine passare puntatori con quello originale (cioè Mappa = newMap)

+0

Ho bisogno di scorrere i nuovi valori aggiunti –

+0

quindi fare un ciclo while e continuare così fino a quando non hai finito. – Ahmad

2

iterare su una copia ed è possibile aggiungere/rimuovere bene:

for (Map.Entry<Long, Integer> e : new LinkedHashMap<Long, Integer>(map).entrySet()){ 
    map.remove(k); 
    map.put(x, value); 
} 

non è nemmeno alcun più righe di codice, perché le ims copia fatta in-line tramite il costruttore di copia. LinkedHashMap è stato scelto per preservare l'ordine di iterazione (se questo è importante).

1

Un esempio di snippet di codice per la rimozione di un elemento dalla mappa è riportato di seguito.

for(Iterator<Map.Entry<Long, Integer>> it = map.entrySet().iterator();it.next();) 
{ 
    Map.Entry<String, String> entry = it.next(); 
if(//some logic)  
it.remove(); 
} 

Se il codice comporta un sacco di aggiunta e la rimozione, si potrebbe semplicemente voler utilizzare ConcurrentHashMap. ConcurrentHashMap

Problemi correlati