Hogyan kerülhető el a ConcurrentModificationException kivétel a gyűjtemény bejárásakor?
sobes.tech MI
Válasz az MI-től
Annak érdekében, hogy elkerüljük a ConcurrentModificationException-t a kollekciók bejárásakor, a következő megközelítéseket lehet alkalmazni:
-
Szálbiztos kollekciók használata: A
java.util.concurrentbiztosít szálbiztos alternatívákat a standard kollekciókhoz. Például:CopyOnWriteArrayListaArrayListhelyettCopyOnWriteArraySetaHashSethelyettConcurrentHashMapaHashMaphelyett
// Példa CopyOnWriteArrayList használatára 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"); // Az iterator nem dob `ConcurrentModificationException`-t Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); System.out.println(element); // A kollekció módosítása iterálás közben biztonságos if (element.equals("B")) { list.remove(element); } } System.out.println("Végső lista: " + list); } } -
A kollekció zárolása: Szinkronizálja a hozzáférést a kollekcióhoz a
synchronizedvagy ajava.util.concurrent.lockshasználatával.// Példa szinkronizált blokkal 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) { // A kollekció zárolása Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); System.out.println(element); // Itt nem szabad módosítani a kollekciót, ha más szál hozzáférhet } } // A kollekció módosítása a szinkronizált blokk kívül vagy más szál által // még mindig `ConcurrentModificationException`-t okozhat párhuzamos iterálás során } } -
Iterator használata az elemek törléséhez: Ha elemeket kell törölni az iterálás közben, használja az iterator
remove()metódusát (ha támogatott a kollekció).// Törlés példája az Iterator.remove() segítségével 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); // Az elem biztonságosan törölhető az iterator segítségével if (element.equals("B")) { iterator.remove(); } } System.out.println("Végső lista: " + list); } } -
Másolat iterálása: Hozzon létre másolatot a kollekcióból, és azzal iteráljon. A módosítások az eredeti kollekción nem befolyásolják az iterációt.
// Másolaton való iterálás példája 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"); // Másolat készítése az iteráláshoz List<String> copyList = new ArrayList<>(list); for (String element : copyList) { System.out.println(element); // A kollekció módosítása az eredeti listán a másolaton való iterálás közben if (element.equals("B")) { list.remove(element); } } System.out.println("Végső lista: " + list); } }
A megközelítés kiválasztása a konkrét követelményektől függ: szükséges-e a kollekció módosítása az iterálás közben, mennyire fontos a teljesítmény, és a kód több szálon fut-e. A CopyOnWriteArrayList/CopyOnWriteArraySet akkor alkalmas, ha az olvasások száma jelentősen nagyobb, mint az írásoké. A zárolás akkor megfelelő, ha a módosítások ritkák, de lehetnek gyakrabban, mint a CopyOnWrite használatával. Az Iterator.remove() vagy a másolat iterálása akkor alkalmazható, ha a módosítások csak egy iteráció vagy szál keretében történnek.