2013-10-01 19 views
6
nesne adlarım positiveCoOrdinate and negativeCoOrdinates.

Özel durumu "ana" iş parçacığında nasıl giderebilirim java.util.ConcurrentModificationException

Aşağıdaki koşullarla PositiveCoOrdinates denetliyorum ve negativeCoOrdinates'a karşılık gelen noktayı ekleyerek positiveCoOrdinates'dan silme işlemini yerine getiriyor.

HashMap<Integer, Point3d> positiveCoOrdinates=duelList.get(1); 
    HashMap<Integer, Point3d> negativecoOrdinates=duelList.get(2); 
    //condition 
    Set<Integer> set=positiveCoOrdinates.keySet(); 
    for (Integer pointIndex : set) { 
     Point3d coOrdinate=positiveCoOrdinates.get(pointIndex); 
     if (coOrdinate.x>xMaxValue || coOrdinate.y>yMaxValue || coOrdinate.z>zMaxValue) { 
      negativecoOrdinates.put(pointIndex, coOrdinate); 
      positiveCoOrdinates.remove(pointIndex); 
     } 
    } 

Ekleme yaparken, silme işlemi sırasında aşağıdaki hatayı alıyorum.

benim test için
Exception in thread "main" java.util.ConcurrentModificationException 
at java.util.HashMap$HashIterator.nextEntry(Unknown Source) 
at java.util.HashMap$KeyIterator.next(Unknown Source) 
at PlaneCoOrdinates.CoordinatesFiltering.Integration(CoordinatesFiltering.java:167) 
at PlaneCoOrdinates.CoordinatesFiltering.main(CoordinatesFiltering.java:179) 

, ben If condition.It çalışma cezası içeride System.out.println(coOrdinate.x); deyimi söz.

If koşulunda 2 satır (Yukarıda bahsettiklerim) eklediğimde, hata atıyor.

Bunu nasıl düzeltebilirim?

Teşekkürler.

+0

"entrySet()" –

cevap

11

kolay yolu anahtar kümesi bir kopyasını yapmaktır: Eğer positiveCoOrdinates oynamamıza çünkü bir Iterator kullanırken sorun oluşur

Set<Integer> set= new HashSet<Integer>(positiveCoOrdinates.keySet()); 

o tuşları dolaşır.

Ayrıca kodunuzu yeniden düzenleyebilir ve giriş kümesi üzerinde bir yineleyici kullanabilirsiniz. Bu daha iyi bir yaklaşım olacaktır. Eğer çalışma zamanında toplanmasını değiştirmek isterseniz

Set<Entry<Integer, Point3d>> entrySet = positiveCoOrdinates.entrySet(); 

    for (Iterator<Entry<Integer, Point3d>> iterator = entrySet.iterator(); iterator.hasNext();) { 
     Entry<Integer, Point3d> entry = iterator.next(); 
     Point3d coOrdinate = entry.getValue(); 
     if (coOrdinate.x > xMaxValue || coOrdinate.y > yMaxValue 
       || coOrdinate.z > zMaxValue) { 
      Integer pointIndex = entry.getKey(); 
      negativecoOrdinates.put(pointIndex, coOrdinate); 
      iterator.remove(); 
     } 
    } 
+0

İyi yaklaşım eşleştirmesi kullanılarak yeni elde ettiğiniz bir anahtardan kaçınabilirsiniz. – Woody

+3

Veya "Yineleyici" kullanabilir. – SudoRahul

+0

Harika çalışıyor ... – Hanumath

0

, sen Iterator yerine döngü için geliştirilmiş kullanmak gerekir. Geliştirilmiş döngü için yalnızca salt okunur işlevler sağladığından. Sen geliştirilmiş for-each döngü kullanmayan remove() tekrarlanan koleksiyonundan olabilir

Iterator<Entity> iterator = collection.Iterator(); 
while(iterator.hasNext()){ 
    //DO Your Stuff 
    iterator.remove(); // this function call remove the element from collection at run time 
} 
2

: Aşağıdaki Yineleyici örnektir. for-each döngü, örtülü olarak Iterator<Integer> kullanır. JavaDoc açıkça

yineleyiciler bu sınıfın tümü tarafından döndürülen belirtiyor "toplama görüntüsü yöntemleri" dir başarısız hızlı: yineleyici oluşturulduktan sonra harita yapısal haricinde herhangi bir şekilde, herhangi zamanda değiştirilirse yineleyicinin kendi remove() yöntemini kullanarak, yineleyici bir ConcurrentModificationException'u atar. Bu nedenle, eşzamanlı olarak modifikasyonunda, iteratör 'dan ziyade, belirsiz bir zaman zarfında belirlenemeyen bir zaman içinde riskli, belirleyici olmayan davranışlar yerine hızlı ve temiz bir şekilde başarısız olur.

for-each döngü, dahili olarak bir yineleyici oluşturur ve kümeyi geçmek için bunu kullanır. Ardından, kümenin yapısını değiştirirsiniz ... ve yineleyicinin başarısız olması gerekir. Şey, yineleyicinin yöntemlerine erişiminiz olmamasıdır, dolayısıyla Iterator<Integer>'u açıkça kullanmalısınız. Oluşturulan çaprazlama bayt kodu aynı olacak, tek farkı, siz onu geçerken listeden öğeleri kaldırabilmeniz.Eğer yineleyiciler ve bunların fonksiyonu ile aşina değilseniz

Set<Integer> set = positiveCoOrdinates.keySet(); 
for (Iterator<Integer> iterator = set.iterator(); iterator.hasNext();) { 
    Integer pointIndex = iterator.next(); 
    Point3d coOrdinate = positiveCoOrdinates.get(pointIndex); 
    if (coOrdinate.x>xMaxValue || coOrdinate.y>yMaxValue || coOrdinate.z>zMaxValue) { 
     negativecoOrdinates.put(pointIndex, coOrdinate); 
     iterator.remove(pointIndex); // this line changed! 
    } 
} 

, the Oracle tutorial on Collections bkz:

Bir Iterator Bir koleksiyon boyunca hareketlerini ve öğeleri kaldırmak sağlayan bir nesne olduğu Seçmeli, isteniyorsa. Bir koleksiyon için, iterator() yöntemini çağırarak bir Iterator olsun.

Yineleme sırasında koleksiyonunu değiştirmenin tek güvenli yolu, Iterator.remove() olduğunu unutmayın; temeldeki koleksiyonun başka bir şekilde değiştirilmiş olması durumunda, yineleme devam ediyorsa, davranış belirtilmez.

  • akım elemanı çıkarın: yerine for-each yapının

    Kullanım Iterator size gerektiğinde. for-each yapısı yineleyiciyi gizler, böylece remove()'u arayamazsınız. Bu nedenle, for-each yapısı filtreleme için kullanılamaz. Başka bir tarafından okunurken bu çok yaygın sorun için René tarafından nedenini işaret edildiği gibi

0

bir koleksiyona eşzamanlı değişiklik olduğunu.

Sen CopyOnWriteArrayLit gibi ConcurrentHashMap veya koleksiyonları kullanmaktadır, ancak yaklaşımlar konularında bu tür çözecek bir yineleme sırasında biraz expensive ve basit değiştiricileri aynı koleksiyonun okuma ortadan kaldırmak için kodlamak için olabileceğini dikkat edebilirsiniz.

İlgili konular