2013-05-19 11 views
8

Chcę napisać kod jak ten -Jak usunąć i dodać elementy do TreeMap podczas iteracji?

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

ale mam java.util.ConcurrentModificationException Próbowałem użyć Iterator również, ale mam ten sam Exception

+4

@ZouZou I googled o to i znalazłem to pytanie na pierwszym miejscu. Google to za mało, potrzebna jest też treść :-) – peterh

+0

Czy możesz dołączyć kod do iteratora. Powyższy kod z pewnością da wyjątek modyfikacji równoczesnej. Przechodzisz przez zestaw kluczy, a także zmieniasz mapę w tym samym czasie. To przepis na katastrofę. – SamDJava

+0

Dodano odpowiedź poniżej z przykładowym kodem. – SamDJava

Odpowiedz

7

Explaintion dlaczego to spowodowane ConcurrentModificationException

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

dla każdej pętli również wewnętrznie utworzyć iterator z entrySet z map. Podczas iteracji na mapie zmodyfikowałeś strukturę mapy poprzez ponowne umieszczenie wartości na mapie (map.put(x,value)), co powoduje, że ta ConcurrentModificationException.

Jest jeszcze dobrze wyjaśnione documentation -

W iteratorów zwracanych przez wszystkich z tej klasy jest „widok zbiórki metody” to fail-szybko: jeśli mapa jest strukturalnie zmodyfikowane w dowolnym czasie po iterator jest tworzony w dowolny sposób z wyjątkiem iteracyjnej metody iteratora, iterator wygeneruje wyjątek ConcurrentModificationEx.W związku z tym, w obliczu równoczesnej modyfikacji , iterator ulega awarii szybko i czysto, zamiast ryzykować arbitralne, niedeterministyczne zachowanie w nieokreślonym czasie. w przyszłości.

Jak rozwiązać ten -

należy zmienić zmianą struktury tej mapy podczas iteracji, można wstawić te wartości później, jak utrzymać tymczasową mapę i dodać ten jeden raz iteracji się skończył praca.

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

trzeba będzie utworzyć kopię mapy z użyciem kopii konstruktor. Teraz wykonaj iterację 1 i zmodyfikuj drugą mapę. Zakładam, że nie trzeba będzie powtarzać nowo dodanej wartości, ponieważ nie ma to większego sensu.

Możesz osiągnąć swoje zadanie, tworząc kopię, ponieważ klucze pozostaną takie same w obu.

EDIT:

nie sądzę, jest to dobry pomysł, aby iteracyjne nowo dodanego elementu do HashMap. Jeśli sprawdzisz api dostarczone przez Iterator, znajdziesz tylko metodę usuwania, nie ma w niej metody dodawania. Istnieje powód tego i możesz sprawdzić do tego javadoc. Teraz przechodzimy do punktu, w jaki sposób iterować nowo dodany element.

  1. Utwórz kopię swojego numeru HashMap. Będziesz więc iterować jeden i modyfikować drugi Map.
  2. Jako że wymagane jest zarówno dodawanie, jak i usuwanie elementów w Map, chciałbym użyć do tego celu ListIterator [różni się on od normalnego Iterator].
  3. Zdobędę keyset mapy 1 i przekonwertuję ją na listę przy użyciu ArrayList(Collection<? extends E> c).
  4. teraz będę się ListIterator z List utworzonego w kroku 3, a także dodawać, usuwać elementy w ListIterator jak również w MAP2 [Pamiętaj trzeba dodawać, usuwać zarówno w ListIterator i MAP2].
+0

Nie muszę powtarzać nad nowymi wartościami nowe dodane wartości będą większe niż bieżące , więc potrzebuję ich powtórzyć –

+0

zobacz moją edycję. Za pomocą nowo dodanych kroków możesz dodawać i usuwać oba. – Lokesh

0

Ponieważ nie możesz tego zrobić.

Prostym rozwiązaniem jest użycie innego tymczasowego mapę, gdzie można umieścić żądane wartości i wreszcie przełączyć wskazówek z pierwotnego (tj Map = newMap)

+0

Potrzebuję do iteracji nad nowymi wartościami dodanymi –

+0

następnie wykonaj pętlę while i rób to, aż skończysz. – Ahmad

2

iteracyjne nad kopią i można dodawać/usuwać dobrze:

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

To nie ma nawet więcej linii kodu, ponieważ IMS kopia wykonana w-line za pośrednictwem konstruktora kopii. LinkedHashMap został wybrany, aby zachować kolejność iteracji (jeśli to ma znaczenie).

1

Przykładowy fragment kodu do usunięcia elementu z mapy podano poniżej.

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

Jeśli twój kod wymaga dużo dodawania i usuwania, możesz po prostu chcieć użyć ConcurrentHashMap. ConcurrentHashMap

Powiązane problemy