본문 바로가기

Language/Java

[Java/ERROR] ConcurrentModificationException

상황

주어진 문자열로 재귀적인 방법을 사용해서 집합을 만들기 위해서 다음과 같은 코드를 작성하였다. 

public ArrayList<String> makeSet(ArrayList<String> prev, String firstStr, String subStr){

        ArrayList<String> result = new ArrayList<>();
        if(subStr.equals("")){
            result.add("");
            result.add(firstStr);
            return result;
        }

        prev = makeSet(prev, String.valueOf(subStr.charAt(0)), subStr.substring(1));

        result = prev;
        for(String s : result){
            result.add(firstStr+s);
        }

        Collections.sort(result);

        return result;
    }

firstStr를 제외한 subStr로 만들어진 집합을 ArrayList<String> prev로 할당받고, result에 기존 집합(prev)를 할당하고, result를 순회하면서 firstStr를 추가한 String을 추가하였는데 다음과 같이 ConcurrentModificationException이 발생하였다. 

 

 

에러코드

 

 

원인

이 에러는 허용되지 않았을 때 동시적으로 object를 수정하려고 시도할 때 발생한다고 하며 주로 Java Collection Classes 객체를 순회하면서 요소를 삭제하거나 변경을 할 때 발생한다.

 

예를 들어, 다음과 같이 list를 순회하면서 value가 3인 값이 있으면 list에서 해당 value를 삭제하는 코드이다. 

public class Concurrentmodificationexception {  
  
    public static void main(String[] args) {  
        ArrayList<Integer> list = new ArrayList<>();  
  
        list.add(1);  
        list.add(2);  
        list.add(3);  
        list.add(4);  
        list.add(5);  
  
        Iterator<Integer> it = list.iterator();  
        while (it.hasNext()) {                   
            Integer value = it.next();              
            System.out.println("List Value:" + value);  
            if (value.equals(3))  
                list.remove(value);  
        }  
  
    }  
  
}

iterator로 list를 순회하면서 우리는 이것을 동시적으로 수정하려고 했기 때문에 발생하는 문제이다. Index가 변경되어 일부 요소는 순회하지 않을 수 있다. List에서 문제가 발생할 수 있는 것을 감지하여 ConcurrentModificationException를 발생시킨다.

 

 

해결방안

public ArrayList<String> makeSet(ArrayList<String> prev, String firstStr, String subStr){
        System.out.println("firstStr = " + firstStr);
        System.out.println("subStr = " + subStr);
        ArrayList<String> result = new ArrayList<>();
        if(subStr.equals("")){
            result.add("");
            result.add(firstStr);
            return result;
        }
        
        prev = makeSet(prev, String.valueOf(subStr.charAt(0)), subStr.substring(1));
        
        for(String s : prev){
            result.add(s);
            result.add(firstStr+s);
        }

        Collections.sort(result);
        
        return result;
    }

다음과 같이 prev를 순회하면서 추가는 result에 하도록 코드를 작성했다. 

 

혹은 크기가 변하지 않는 배열을 사용하거나 synchronize 키워드를 사용하는 방법도 있다.

 

'Language > Java' 카테고리의 다른 글

[Java] Map 인터페이스  (0) 2023.05.15
[Java] Collection 프레임워크  (0) 2023.05.15
[Java] Object 클래스 메소드 - toString()  (0) 2022.11.07
[Java] Object 클래스  (0) 2022.11.07
[Java] 기타 제어자  (0) 2022.11.07