Kā izvairīties no izņēmuma ConcurrentModificationException, pārlūkojot kolekciju?
sobes.tech AI
Atbilde no AI
Lai izvairītos no ConcurrentModificationException kolekcijas iterācijas laikā, var izmantot šādus pieejas:
-
Izmantot sērijai drošas kolekcijas:
java.util.concurrentnodrošina sērijai drošas alternatīvas standarta kolekcijām. Piemēram:CopyOnWriteArrayListvietāArrayListCopyOnWriteArraySetvietāHashSetConcurrentHashMapvietāHashMap
// Piemērs ar CopyOnWriteArrayList 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"); // Iterators neizraisa `ConcurrentModificationException` Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); System.out.println(element); // Kolekcijas maiņa iterācijas laikā ir droša if (element.equals("B")) { list.remove(element); } } System.out.println("Galīgais saraksts: " + list); } } -
Bloķēt kolekciju: Sinhronizēt piekļuvi kolekcijai, izmantojot
synchronizedvaijava.util.concurrent.locks.// Piemērs ar sinhronizētu bloku 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) { // Bloķē kolekciju piekļuvei Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); System.out.println(element); // Šeit nedrīkst mainīt kolekciju, ja cits pavedienis var piekļūt } } // Kolekcijas maiņa ārpus sinhronizētā bloka vai citā pavedienā // joprojām var izraisīt `ConcurrentModificationException`, ja notiek paralēla iterācija } } -
Izmantot iteratoru elementu dzēšanai: Ja nepieciešams dzēst elementus iterācijas laikā, izmantojiet
remove()metodi no iteratora (ja kolekcija to atbalsta).// Piemērs ar `Iterator.remove()` 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); // Elementa dzēšana ar iteratoru ir droša if (element.equals("B")) { iterator.remove(); } } System.out.println("Galīgais saraksts: " + list); } } -
Iterēt kopiju kolekcijas: Izveidot kopiju un to iterēt. Izmaiņas sākotnējā kolekcijā neietekmēs iterāciju pa kopiju.
// Piemērs ar kopijas iterāciju 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"); // Izveidojam kopiju iterācijai List<String> copyList = new ArrayList<>(list); for (String element : copyList) { System.out.println(element); // Var mainīt oriģinālo kolekciju iterācijas laikā if (element.equals("B")) { list.remove(element); } } System.out.println("Galīgais saraksts: " + list); } }
Izvēlētais pieejas veids ir atkarīgs no konkrētajām prasībām: vai ir nepieciešams mainīt kolekciju iterācijas laikā, cik svarīgs ir veiktspējas un vai kods darbojas daudzprocesuālas vides apstākļos. CopyOnWriteArrayList/CopyOnWriteArraySet ir piemēroti, kad lasījumu ir daudz vairāk nekā rakstu. Bloķēšana ir piemērota, kad izmaiņas notiek retāk, bet tās var būt biežākas nekā ar CopyOnWrite. Iterator.remove() vai kopijas iterācija ir piemērotas, kad izmaiņas notiek tikai vienas iterācijas vai pavediena laikā.