Hoe voorkom je een ConcurrentModificationException bij het doorlopen van een collectie?
sobes.tech AI
Antwoord van AI
Om te voorkomen dat er een ConcurrentModificationException optreedt tijdens het itereren over een collectie, kunnen de volgende benaderingen worden gebruikt:
-
Gebruik thread-veilige collecties:
java.util.concurrentbiedt thread-veilige alternatieven voor standaardcollecties. Bijvoorbeeld:CopyOnWriteArrayListin plaats vanArrayListCopyOnWriteArraySetin plaats vanHashSetConcurrentHashMapin plaats vanHashMap
// Voorbeeld met 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"); // Iterator werpt geen ConcurrentModificationException uit Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); System.out.println(element); // Het veilig om de collectie te wijzigen tijdens iteratie if (element.equals("B")) { list.remove(element); } } System.out.println("Eindlijst: " + list); } } -
Vergrendel de collectie: Synchroniseer toegang tot de collectie met
synchronizedofjava.util.concurrent.locks.// Voorbeeld met gesynchroniseerde blok 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) { // Vergrendel de collectie Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); System.out.println(element); // Het is niet toegestaan om de collectie hier te wijzigen als een andere thread toegang kan krijgen } } // Het wijzigen van de collectie buiten de gesynchroniseerde blok of door een andere thread // kan nog steeds een ConcurrentModificationException veroorzaken tijdens parallelle iteratie } } -
Gebruik iterator voor het verwijderen van elementen: Als je elementen wilt verwijderen tijdens het itereren, gebruik dan de
remove()-methode van de iterator (indien ondersteund door de collectie).// Voorbeeld van verwijderen met 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); // Veilig element verwijderen via iterator if (element.equals("B")) { iterator.remove(); } } System.out.println("Eindlijst: " + list); } } -
Itereer over een kopie van de collectie: Maak een kopie van de collectie en doorloop deze. Wijzigingen in de originele collectie beïnvloeden de kopie niet.
// Voorbeeld van iteratie over een kopie 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"); // Maak een kopie voor iteratie List<String> copyList = new ArrayList<>(list); for (String element : copyList) { System.out.println(element); // Je kunt de originele collectie wijzigen tijdens het itereren over de kopie if (element.equals("B")) { list.remove(element); } } System.out.println("Eindlijst: " + list); } }
De keuze van aanpak hangt af van de specifieke vereisten: of je de collectie tijdens het itereren moet wijzigen, hoe belangrijk de prestaties zijn en of de code in een multithread-omgeving draait. CopyOnWriteArrayList/CopyOnWriteArraySet zijn geschikt wanneer er veel gelezen wordt en weinig geschreven. Vergrendeling is geschikt wanneer wijzigingen zeldzamer zijn, maar mogelijk frequenter dan bij gebruik van CopyOnWrite. Gebruik van Iterator.remove() of iteratie over een kopie is geschikt wanneer wijzigingen alleen binnen één iteratie of thread plaatsvinden.