들어가기 전

필자가 이 내용을 다루게 된 이유는 업무를 보다가 ArrayList로 담긴 데이터를 순회하면서 삭제하다가  ConcurrentModificationException 예외를 접하게 되었습니다. 자바를 여태 하면서 IndexOutOfBoundsException는 많이 봤어도 ConcurrentModificationException라는 예외는 처음 봐서 이거에 대해 알아보고 싶었고 그리고 이 문제를 겪는 사람들이 많을 거라고 생각되어 다루게 되었습니다.  이제 문제의 원인이랑 해결방법에 대해서 알아보겠습니다.

 

원인

원인에 대해 먼저 알아보기 전 원인이 된 코드를 먼저 보겠습니다.

 

public class Test {

    public static void main(String[] args) {
        List<String> firstList = new ArrayList<>();
        firstList.add("자바");
        firstList.add("스프링");
        firstList.add("JPA");
        firstList.add("데이터베이스");
        firstList.add("네트워크");
        List<String> secondList = new ArrayList<>();
        secondList.add("자바스크립트");
        secondList.add("JPA");
        secondList.add("자바");
        secondList.add("파이썬");

        for (String firstStr : firstList) {
            for (String secondStr : secondList) {
                if (secondStr.contains(firstStr)) {
                    secondList.remove(secondStr);
                }
            }
        }


    }


위와 같은 코드를 작성하고 리스트에 담겨있는 데이터를 삭제할 경우 ConcurrentModificationException가 발생하게 됩니다.

 

원인
리스트가 순회하면서 데이터를 삭제를 하는 도중에 인덱스가 바뀌게 되면서
현재 가리키고 있는 인덱스가 리스트의 크기보다 커지면 발생합니다.

 

 

문제의 원인을  직접 눈으로 파악하고 싶으시면 아래의 사진과 같이 포인트를 찍고 디버깅해보시기 바랍니다.

 

 

필자가 예시로 만든 코드

 

 

 

자바에서 제공해주는 클래스 

 

package java.util
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

 

위 클래스에 정의된 메서드

 

 

 

해결 방법

 

해결방법으로는 위에 필자가 예시로 만든 일부 코드만 수정하면 됩니다.

 

해결방법 1

 

for (String firstStr : firstList) {
            for (String secondStr : secondList) {
                if (secondStr.contains(firstStr)) {
                    secondList.remove(secondStr);
                    break;
                }
            }
        }

 

  • break문을 추가해줘서 오류를 피할 수 있습니다.

 

해결방법 2

 

for (String firstStr : firstList) {
    for (int i = secondList.size() - 1; i >= 0; i--)
        if (secondList.get(i).contains(firstStr)) {
            secondList.remove(i);
        }
    }

 

  • 삭제할 리스트를 역순으로 삭제하면 오류를 피할 수 있습니다.

 

 

'Java' 카테고리의 다른 글

[Java] Static Block 실행 시점  (2) 2024.03.15
[Java] this란?  (0) 2022.05.01
[Java] 함수와 메서드의 개념 및 차이, 스택 메모리  (1) 2022.02.21