[java] ArrayList에서 요소를 반복하고 제거 할 때 java.util.ConcurrentModificationException을 피하는 방법

반복하고 싶은 ArrayList가 있습니다. 그것을 반복하면서 동시에 요소를 제거해야합니다. 분명히 이것은을 던집니다 java.util.ConcurrentModificationException.

이 문제를 처리하는 가장 좋은 방법은 무엇입니까? 먼저 목록을 복제해야합니까?

루프 자체가 아닌 코드의 다른 부분에서 요소를 제거합니다.

내 코드는 다음과 같습니다

public class Test() {
    private ArrayList<A> abc = new ArrayList<A>();

    public void doStuff() {
        for (A a : abc)
        a.doSomething();
    }

    public void removeA(A a) {
        abc.remove(a);
    }
}

a.doSomething호출 할 수 있습니다 Test.removeA();



답변

두 가지 옵션 :

  • 루프 내에서 해당 목록에 추가 하여 제거하려는 값 목록을 작성한 다음 originalList.removeAll(valuesToRemove)끝에서 호출 하십시오.
  • remove()반복자 자체 에서 메소드를 사용하십시오 . 이는 향상된 for 루프를 사용할 수 없음을 의미합니다.

두 번째 옵션의 예로, 목록에서 길이가 5보다 큰 문자열을 제거하십시오.

List<String> list = new ArrayList<String>();
...
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
    String value = iterator.next();
    if (value.length() > 5) {
        iterator.remove();
    }
}


답변

ArrayList의 JavaDoc에서

이 클래스의 이터레이터와 listIterator 메소드에 의해 리턴 된 이터레이터는 빠르다 : 이터레이터가 작성된 후 언제라도리스트가 구조적으로 수정 되면, 이터레이터 자신의 remove 또는 add 메소드를 제외하고 어떤 식 으로든 이터레이터는 ConcurrentModificationException을 발생시킨다.


답변

고급 “for loop”의 목록에서 값을 제거하려고합니다. 코드에서 수행 한 트릭을 적용하더라도 불가능합니다. 더 좋은 방법은 다른 조언과 같이 반복자 수준을 코딩하는 것입니다.

사람들이 전통적인 for 루프 접근법을 어떻게 제안하지 않았는지 궁금합니다.

for( int i = 0; i < lStringList.size(); i++ )
{
    String lValue = lStringList.get( i );
    if(lValue.equals("_Not_Required"))
    {
         lStringList.remove(lValue);
         i--;
    }
}

이것은 잘 작동합니다.


답변

전통적인 방식으로 배열을 반복해야합니다.

목록에서 요소를 제거 할 때마다 이후의 요소가 푸시됩니다. 반복 요소 이외의 요소를 변경하지 않는 한 다음 코드가 작동합니다.

public class Test(){
    private ArrayList<A> abc = new ArrayList<A>();

    public void doStuff(){
        for(int i = (abc.size() - 1); i >= 0; i--)
            abc.get(i).doSomething();
    }

    public void removeA(A a){
        abc.remove(a);
    }
}


답변

Java 8에서는 Collection Interface를 사용하고 removeIf 메소드를 호출하여이를 수행 할 수 있습니다.

yourList.removeIf((A a) -> a.value == 2);

자세한 내용은 여기를 참조하십시오


답변

정상적인 방법으로 루프를 수행하십시오 java.util.ConcurrentModificationException. 액세스되는 요소와 관련된 오류입니다.

그래서 시도하십시오 :

for(int i = 0; i < list.size(); i++){
    lista.get(i).action();
}


답변

목록을 반복하는 동안 요소를 제거하려는 경우 가능합니다. 내 예를 아래에서 보자.

ArrayList<String>  names = new ArrayList<String>();
        names.add("abc");
        names.add("def");
        names.add("ghi");
        names.add("xyz");

위의 배열 목록 이름이 있습니다. 그리고 위 목록에서 “def”이름을 제거하고 싶습니다.

for(String name : names){
    if(name.equals("def")){
        names.remove("def");
    }
}

위의 코드는 ConcurrentModificationException을 발생 시킵니다.반복하는 동안 목록을 수정하기 때문에 예외를 발생시킵니다.

이런 식으로 Arraylist에서 “def”이름을 제거하려면

Iterator<String> itr = names.iterator();
while(itr.hasNext()){
    String name = itr.next();
    if(name.equals("def")){
        itr.remove();
    }
}

위 코드는 반복자를 통해 Arraylist에서 “def”이름을 제거하고 배열을 인쇄하려고하면 아래 출력을 볼 수 있습니다.

출력 : [abc, ghi, xyz]