개발관련/오류노트

컬렉션을 반복하여 루프에서 개체를 제거 할 때 ConcurrentModificationException 방지

Rateye 2021. 6. 9. 10:18
728x90
반응형
질문 : 컬렉션을 반복하여 루프에서 개체를 제거 할 때 ConcurrentModificationException 방지

ConcurrentModificationException 때문에 다음을 수행 할 수 없다는 것을 모두 알고 있습니다.

for (Object i : l) {
    if (condition(i)) {
        l.remove(i);
    }
}

그러나 이것은 분명히 때때로 작동하지만 항상 그런 것은 아닙니다. 다음은 몇 가지 특정 코드입니다.

public static void main(String[] args) {
    Collection<Integer> l = new ArrayList<>();

    for (int i = 0; i < 10; ++i) {
        l.add(4);
        l.add(5);
        l.add(6);
    }

    for (int i : l) {
        if (i == 5) {
            l.remove(i);
        }
    }

    System.out.println(l);
}

물론 결과는 다음과 같습니다.

Exception in thread "main" java.util.ConcurrentModificationException

여러 스레드가 수행하지 않더라도. 어쨌든.

이 문제에 대한 최선의 해결책은 무엇입니까? 이 예외를 발생시키지 않고 루프에서 컬렉션에서 항목을 제거하려면 어떻게해야합니까?

여기서도 ArrayList 아닌 임의의 Collection get 의존 할 수 없습니다.

답변

Iterator.remove() 는 안전하며 다음과 같이 사용할 수 있습니다.

List<String> list = new ArrayList<>();

// This is a clever way to create the iterator and call iterator.hasNext() like
// you would do in a while-loop. It would be the same as doing:
//     Iterator<String> iterator = list.iterator();
//     while (iterator.hasNext()) {
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
    String string = iterator.next();
    if (string.isEmpty()) {
        // Remove the current element from the iterator and the list.
        iterator.remove();
    }
}

Iterator.remove() 는 반복 중에 컬렉션을 수정하는 유일한 안전한 방법입니다. 반복이 진행되는 동안 기본 컬렉션이 다른 방식으로 수정되면 동작이 지정되지 않습니다.

출처 : docs.oracle> 컬렉션 인터페이스

마찬가지로 ListIterator 있고 항목을 추가 ListIterator#add 사용할 수 있습니다. 같은 이유로 Iterator#remove 를 사용할 수 있습니다. 허용하도록 설계되었습니다.

귀하의 경우 목록에서 제거하려고했지만 콘텐츠를 반복하는 동안 Map put

출처 : https://stackoverflow.com/questions/223918/iterating-through-a-collection-avoiding-concurrentmodificationexception-when-re
728x90
반응형