Sobes.tech
Middle

Bir koleksiyon üzerinde gezinirken ConcurrentModificationException istisnasını nasıl önlersiniz?

sobes.tech yapay zeka

AI'dan gelen yanıt

Bir koleksiyon üzerinde gezinirken ConcurrentModificationException hatasını önlemek için aşağıdaki yaklaşımları kullanabilirsiniz:

  1. İş parçacığı güvenli koleksiyonlar kullanmak: java.util.concurrent, standart koleksiyonlara göre iş parçacığı güvenli alternatifler sunar. Örneğin:

    • CopyOnWriteArrayList yerine ArrayList
    • CopyOnWriteArraySet yerine HashSet
    • ConcurrentHashMap yerine HashMap
    // CopyOnWriteArrayList ile örnek
    import java.util.concurrent.CopyOnWriteArrayList;
    import java.util.Iterator;
    
    public class ConcurrentCollectionExample {
        public static void main(String[] args) {
            CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
            list.add("A");
            list.add("B");
            list.add("C");
    
            // İteratör, ConcurrentModificationException fırlatmaz
            Iterator<String> iterator = list.iterator();
            while (iterator.hasNext()) {
                String element = iterator.next();
                System.out.println(element);
                // Koleksiyonu değiştirmek güvenlidir
                if (element.equals("B")) {
                    list.remove(element);
                }
            }
            System.out.println("Final liste: " + list);
        }
    }
    
  2. Koleksiyonu kilitlemek: synchronized veya java.util.concurrent.locks kullanarak koleksiyona erişimi senkronize edin.

    // Senkronize blok ile örnek
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class SynchronizedCollectionExample {
       public static void main(String[] args) {
           List<String> list = new ArrayList<>();
           list.add("A");
           list.add("B");
           list.add("C");
    
           synchronized (list) { // Koleksiyonu erişim için kilitler
               Iterator<String> iterator = list.iterator();
               while (iterator.hasNext()) {
                   String element = iterator.next();
                   System.out.println(element);
                   // Başka bir iş parçacığı bu blok içinde koleksiyonu değiştiremez
               }
           }
           // Koleksiyon, başka bir iş parçacığında veya blok dışında değiştirilebilir
           // ve yine de paralel iterasyonda ConcurrentModificationException oluşabilir
       }
    }
    
  3. İteratör kullanarak öğeleri kaldırmak: Öğeleri iterasyon sırasında kaldırmanız gerekiyorsa, remove() metodunu kullanın (koleksiyon bunu destekliyorsa).

    // Iterator.remove() kullanımıyla örnek
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class IteratorRemoveExample {
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("A");
            list.add("B");
            list.add("C");
    
            Iterator<String> iterator = list.iterator();
            while (iterator.hasNext()) {
                String element = iterator.next();
                System.out.println(element);
                // Güvenli bir şekilde öğeyi kaldır
                if (element.equals("B")) {
                    iterator.remove();
                }
            }
            System.out.println("Final liste: " + list);
        }
    }
    
  4. Koleksiyonun bir kopyasını dolaşmak: Koleksiyonun bir kopyasını oluşturun ve onu dolaşın. Orijinal koleksiyonda yapılan değişiklikler, kopya üzerinde yapılan iterasyonu etkilemez.

    // Kopya üzerinde dolaşma örneği
    import java.util.ArrayList;
    import java.util.List;
    
    public class CopyIterationExample {
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("A");
            list.add("B");
            list.add("C");
    
            // Dolaşmak için kopya oluştur
            List<String> copyList = new ArrayList<>(list);
    
            for (String element : copyList) {
                System.out.println(element);
                // Orijinal koleksiyonu, kopya üzerinde dolaşırken değiştirebiliriz
                if (element.equals("B")) {
                    list.remove(element);
                }
            }
            System.out.println("Final liste: " + list);
        }
    }
    

Yaklaşım seçimi, belirli gereksinimlere bağlıdır: koleksiyonu iterasyon sırasında değiştirmek gerekiyor mu, performans ne kadar önemli ve kod çok iş parçacıklı ortamda mı çalışıyor. CopyOnWriteArrayList/CopyOnWriteArraySet, okuma işlemleri yazma işlemlerinden çok daha fazla ise uygundur. Kilitleme, değişiklikler daha seyrek ise ve CopyOnWrite'a göre daha sık olabiliyorsa uygundur. Iterator.remove() veya kopya dolaşımı, değişikliklerin yalnızca bir iterasyon veya iş parçacığında gerçekleştiği durumlarda kullanışlıdır.