솔솔

[Java] ConcurrentModificationException 에러 본문

나의보물들/Java

[Java] ConcurrentModificationException 에러

솔솔하네 2024. 7. 13. 18:38
반응형
for(Animal animal : searchAnimals) {
	if(animal.getPetId() != animalPK) {
    	searchAnimals.remove(animal);
    }
}

 

[에러가 나왔던 상황]

미니 프로젝트를 진행하던 중 아래의 3번째 줄 코드에서

ConcurrentModificationException 라는 에러가 났다.

 

[에러가 나온 원인]

ConcurrentModificationException은 번역기로 직역하면 동시수정예외인데

Java에서 컬렉션을 반복하면서 컬렉션의 내용을 수정하려고 할 때 발생하는 에러이다.

ArrayList와 같은 컬렉션에서 for-each 루프를 사용하여 요소를 순회하면서 요소를 제거하면 이 예외가 발생한다.

 

이 에러는 내부적으로 Iterator를 사용하여 컬렉션을 순회할 때 발생하는데

for-each 루프는 Iterator를 사용하며 Iterator는 컬렉션이 수정되었는지 여부를 추적한다.

만약 컬렉션이 순회하는 동안 수정되면 Iterator는 ConcurrentModificationException을 던진다고 한다.

 

[그럼 여기서 왜 Iterator는 컬렉션이 수정되었는지 여부를 추적할까]

⭐️ 데이터 일관성 유지를 위해서⭐️ 

컬렉션을 순회하면서 동시에 수정하면 순회 중인 데이터의 상태가 예기치 않게 변할 수 있고 이는 일관성 문제를 일으킬 수 있는데  

예를 들어 어떤 요소가 삭제되거나 추가되면 현재 순회 중인 인덱스나 포인터가 유효하지 않게 될 수 있다.

Iterator는 이러한 상황을 감지하여 예외를 던짐으로써 데이터 일관성을 유지한다.

 


[해결방법]

removeIf로 삭제하기

searchAnimals.removeIf(animal -> animal.getPetId() != animalPK);

 

- removeIf는 Java8에서 도입되었고 'java.util.Collection' 인터페이스에 추가된 기본 메서드 중 하나로

   컬렉션의 요소를 조건에 따라 제거할 수 있게 해준다고한다. 그리고 내부적으로 Iterator를 사용하여

   안전하게 요소를 제거해 줄 수 있게 해준다고한다.

 

- 그 외의 방법들을 기록한 블로그 첨부

https://codechacha.com/ko/java-concurrentmodificationexception/

 

Java - ConcurrentModificationException 원인 및 해결 방법

ConcurrentModificationException는 보통 리스트나 Map 등, Iterable 객체를 순회하면서 요소를 삭제하거나 변경을 할 때 발생합니다. removeIf, removeAll, Iterable 등의 메소드를 이용하여 리스트 순회 중 요소를

codechacha.com