როგორ ავიცილოთ თავიდან ConcurrentModificationException გამონაკლისი კოლექციის გადათვალვისას?
sobes.tech AI
პასუხი AI-სგან
Коллекцияны аралаганда ConcurrentModificationException болтурбоо үчүн, төмөнкү ыкмаларды колдонсо болот:
-
Туташтыксыз корголгон коллекциялар колдонуу:
java.util.concurrentстандарттык коллекциялардын туташтыксыз альтернативасын камсыз кылат. Мисалы:CopyOnWriteArrayListArrayListордунаCopyOnWriteArraySetHashSetордунаConcurrentHashMapHashMapордуна
// `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"); // Итератор `ConcurrentModificationException` таштабайт Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); System.out.println(element); // Коллекцияны өзгөртүүнү коопсуз жүргүзүү if (element.equals("B")) { list.remove(element); } } System.out.println("Акыркы тизмек: " + list); } } -
Коллекцияны блоктоо: Синхрондоштуруу
synchronizedжеjava.util.concurrent.locksколдонуп коллекторго кирүүнү синхрондоштуруу:// синхрондоштурулган блок менен мисал 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) { // Коллекцияны кирүүгө блоктоо Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); System.out.println(element); // Башка агым коллекторго кире албасын, эгерде ал ошол `synchronized` блокунда болсо } } // Коллекцияны өзгөртүү `synchronized` блоктон тышкары же башка агымда // дагы `ConcurrentModificationException` пайда болушу мүмкүн } } -
Итераторду колдонуп элементтерди өчүрүү: Эгер обуруп жатканда элементтерди өчүрүү керек болсо,
remove()методун колдонуу (эгер колекция аны колдойт):// `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); // Элементти итератор аркылуу коопсуз өчүрүү if (element.equals("B")) { iterator.remove(); } } System.out.println("Акыркы тизмек: " + list); } } -
Көбүрөөк коллекцияны өтүү: Коллекциянын көчүрмөсүн түзүп, аны өтүү. Баштапкы коллекциядагы өзгөртүүлөр көчмөгө таасир этпейт:
// Көчүрмө аркылуу өтүүнүн мисалы 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"); // Өтүүнү үчүн көчүрмө түзүү List<String> copyList = new ArrayList<>(list); for (String element : copyList) { System.out.println(element); // Өтүүнү учурунда оригинал коллекцияны өзгөртсө болот if (element.equals("B")) { list.remove(element); } } System.out.println("Акыркы тизмек: " + list); } }
Тандоо конкреттүү талаптарга жараша болот: коллекцияны өтүү учурунда өзгөртүш керекпи, аткаруу ылдамдыгы канчалык маанилүү жана код көптөгөн агымдарда иштейби. CopyOnWriteArrayList/CopyOnWriteArraySet окуу көп болсо, жазуу аз болсо ылайыктуу. Блоктоо өзгөртүүлөр сирек болсо, бирок CopyOnWrite караганда көбүрөөк болушу мүмкүн. Користонуу Iterator.remove() же көчүрмө аркылуу өтүү бир агымда же өтүүдө гана өзгөртүүлөр болсо колдонулат.