Array List 의 modcount 에 대해 이야기 합 니 다.

저 는 큰 세 가지 찌꺼기 입 니 다.자바 의 기 초 를 복습 하 는 동안 자바 가 정말 점점 절묘 해 지 는 것 을 발 견 했 습 니 다.그래,쓸데없는 소리 그만 하고 오늘 얘 기 좀 하려 고. Array List 의 modcount 속성 입 니 다.
       교체 기 Iterator 는 낯 설 지 않 을 것 입 니 다.Array List,LinkedList,HashSet 등 여러 가지 바 텀 에 서로 다른 용 기 를 실현 합 니 다.예 를 들 어 Array List 바 텀 은 하나의 배열 입 니 다.LinkedList 는 링크 구조 이 고 HashSet 은 해시 표 에 의존 합 니 다.모든 용기 에 자신 만 의 독특한 데이터 구조 가 있 는 상황 에서 고객 이 이런 집합 중의 요 소 를 옮 겨 다 녀 야 한다 면그들 이 어떻게 실현 되 었 는 지 알 필요 가 없다.
     이 용기 들 은 모두 교체 기 에 대한 실현 이 있다.ArrayList 가 져 오기 예 를 들 어 Array List 에 iterator()방법 이 있 음 을 알 수 있 습 니 다.
public Iterator iterator() {
        return new Itr();
    }

방법 은 Itr 대상 을 되 돌려 줍 니 다.Itr 는 Array List 의 내부 클래스 입 니 다.코드 는 다음 과 같 습 니 다.
private class Itr implements Iterator {
    
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;
    
    public boolean hasNext() {
        return cursor < limit;
    }
    
    @SuppressWarnings("unchecked")
    public E next() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        int i = cursor;
        if (i >= limit)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }
    
    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
            limit--;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
}

이 modCount 는 이 교체 기 대상 이 수 정 된 횟수 를 대표 합 니 다.교체 기 대상 마다 수 정 됩 니 다.modCount 는 1.remove 방법 에 이 문구 가 있 습 니 다. expectedModCount = modCount;
Itr 클래스 에 구성원 변수 expected ModCount 가 있 습 니 다.이 값 은 Itr 대상 을 만 들 때 List 의 modCount 값 입 니 다.이 변 수 를 사용 하여 교체 과정 에서 List 대상 이 수정 되 었 는 지 확인 하고 수정 되면 자바 util.Concurrent ModificationException 이상 을 던 집 니 다.Itr 대상 의 next()방법 을 호출 할 때마다 checkForComodification()방법 을 사용 하여 검 사 를 합 니 다.checkForComodification()방법 에서 하 는 일 은 expected ModCount 와 modCount 의 값 이 같 는 지 비교 하 는 것 입 니 다.같 지 않 으 면 다른 대상 이 현재 List 를 조작 하고 있다 고 생각 합 니 다.그 건 Concurrent ModificationException 이상 을 던 집 니 다.예 를 들 어:
public static void main(String[] args) {
		List list = new ArrayList();
		list.add("a");
		list.add("b");
		list.add("c");
		list.add("d");
		Iterator iterator = list.iterator();
		while (iterator.hasNext()) {
			String str = (String) iterator.next();
			if (str.equals("c")) {
				list.remove(str);
			} else {
				System.out.println(str);
			}
		}
	}

결국
a
b
Exception in thread "main" java.util.ConcurrentModificationException

메모:remove 방법 은 iterator 가 아 닌 list 대상 을 호출 합 니 다.list 의 remove 방법 에는 없습니다.  expectedModCount=modCount 문장!
ArrayList 의 remove 방법:
 public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

즉,list.remove(str)가 실 행 된 후 modCount++는 할당 되 지 않 았 습 니 다. expected ModCount,그래서 지금 expected ModCount 는 modCount 와 같 지 않 기 때문에 다음 next()방법 에 있 는 checkForComodification()은 이상 을 던 집 니 다.
list.remove(str)를 iterator.remove()로 바 꾸 면 정상적으로 실 행 됩 니 다.

좋은 웹페이지 즐겨찾기