2013-04-13 3 views
21

반복하는 동안 컬렉션에서 개체를 제거하는 가장 안전한 "아마도 안전한"방법은 먼저 Iterator을 검색하고 필요할 때 루프를 수행하고 제거하는 것입니다. 나는 불행하게도 이해, 그리고 것이 무엇 Iterator의 remove 메서드로 실제로 개체를 제거하는 방법

Iterator iter=Collection.iterator(); 
while(iter.hasNext()){ 
    Object o=iter.next() 
    if(o.equals(what i'm looking for)){ 
     iter.remove(); 
    } 
} 

이 제거
경우, 수행하는 방법에 대한 깊은 기술적 인 설명을 발견하지 않았습니다 :

for(Object o:myCollection().getObjects()){ 
    if(o.equals(what i'm looking for)){ 
     myCollection.remove(o); 
    } 
} 

ConcurrentModificationException를 던질 것인가, 무엇을 "기술 용어로"Iterator.remove()합니까? 개체를 제거하고 루프를 중단하고 루프를 다시 시작합니까?

나는 공식 문서를 참조하십시오

는 "현재 요소를 제거하는 시도가 다음 () 호출에 의해 선행되지 않도록 remove()를 호출하려 할 경우, IllegalStateException를 발생시킵니다.."

부분은 나에게 "일반"루프에서 일어나는 동일한 상황을 생각하게, "현재 요소를 제거"=> (평등 테스트를 수행하고 필요한 경우 제거), 그런데 왜 반복자 루프가 ConcurrentModification- 안전한?

+0

당신이 직접 볼 수 있습니다은 https ://gist.github.com/kibotu/e480bd7505615a7311a6 –

답변

14

Iterator가 요소를 제거하는 방법은 구현에 따라 다르며, 이는 서로 다른 컬렉션에 따라 다를 수 있습니다. 확실히 당신이에있어 루프를 중단하지 않습니다 난 그냥 구현하는 방법을 ArrayList의 반복자 보니 여기에 코드입니다했습니다. 그래서

public void remove() { 
    if (lastRet < 0) 
     throw new IllegalStateException(); 
    checkForComodification(); 

    try { 
     ArrayList.this.remove(lastRet); 
     cursor = lastRet; 
     lastRet = -1; 
     expectedModCount = modCount; 
    } catch (IndexOutOfBoundsException ex) { 
     throw new ConcurrentModificationException(); 
    } 
} 

가 동시에 수정을 검사,를 제거 공공 ArrayList를 를 사용하여 요소를 제거 메소드를 호출하고 목록 수정의 카운터를 증가 시키므로 다음 반복에서 ConcurrentModificationException이 발생하지 않습니다.

+1

'lastRet'이란 무엇입니까? – m0skit0

+1

반복자에 의해 리턴 된 마지막 요소의 색인. 이 요소는 목록에서 방금 제거되었으므로 -1로 설정됩니다. –

+0

자바는 약간 녹슬었지만'ArrayList.this.remove (lastRet) '는 무엇입니까? 왜'ArrayList.this'라고 써야할까요? 그것은 내부 수업인가요? –

17

iterator가 hasNext() 및 next()를 반환 할 항목을 알고 있어야하기 때문에 반복되는 동안 목록을 수정할 수없는 이유는 목록을 수정해야하기 때문입니다. 이 작업이 어떻게

는 구현 고유의 것입니다,하지만 당신은 ArrayList에의 소스 코드를 살펴 가질 수/AbstractList를/LinkedList의 등

또한 어떤 상황에서 당신이 대안으로 다음과 같은 몇 가지 코드를 사용할 수 있습니다 :

List<Foo> copyList = new ArrayList<>(origList); 
for (Foo foo : copyList){ 
    if (condition){ 
    origList.remove(foo); 
    } 
} 

그러나 컬렉션 (단지 얕은 복사) 복사 할 수 있고 제거 할 수있는 요소를 검색 할 수 있기 때문에이 코드는 아마 약간 느리게 실행됩니다.

은 또한 직접 반복자를 사용하는 경우이 변수의 범위를 제한으로 대신 while 루프의 루프를 사용하는 것이 좋습니다 참고 :

for (Iterator<Foo> iterator = myCollection.iterator(); iterator.hasNext();){ 
... 
} 
관련 문제