소 백 일기[List 반복 삭제]

5612 단어 소 백 일기
흰 둥 이 하나,잘 부탁드립니다.
소 백 오늘 퀘 스 트:List 교체 중 요소 삭제
1.소 백 사고:교체 기 를 사용 하여 실현
1)테스트 소스 코드:
    private List rookieList;

    @BeforeEach
    public void initList() {
        //       
        rookieList = new ArrayList(){{
            add("    ");
            add("    ");
            add("    ");
            add("    ");
        }};
    }

    @Test
    public void removeItem() {
        //          
        Iterator rookieIterator = rookieList.iterator();
        //      
        while (rookieIterator.hasNext()) {
            String item = rookieIterator.next();
            if(item.equals("    ")) {
                rookieIterator.remove();
                System.out.println(item +"   ,    ");
            }
        }
        //      
        System.out.println("       :");
        rookieList.forEach(System.out::println);
    }

2)결과 인쇄:
       ,    
       :
    
    
    

 
2.소 백 탐색:원생 List remove 방법 을 이용 하여 왜 Concurrent ModificationException 이상 이 발생 합 니까?
1)테스트 소스 코드:
    @Test
    public void removeItemByList() {
        for(String item:rookieList) {
           if(item.equals("    ")) {
                rookieList.remove(item);
                System.out.println(item +"   ,    ");
            }
        }
        //      
        System.out.println("       :");
        rookieList.forEach(System.out::println);
    }

2)결과 인쇄:
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
    at java.util.ArrayList$Itr.next(ArrayList.java:859)
    at com.wd.IterateTest.removeItemByList(IterateTest.java:27)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at java.util.ArrayList.forEach(ArrayList.java:1257)

3)잘못된 점 찾기:
       // ArrayList:849
       int expectedModCount = modCount;
       
       // ArrayList:858-868
       public E next() {
            checkForComodification(); //    
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        // ArrayList:907-910
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException(); //    
        }

Concurrent ModificationException 이 반복 요소 검사 시 modCount != expected ModCount 가 촉발 합 니 다.그러면 modCount 와 expected ModCount 는 각각 무슨 뜻 을 의미 합 니까?의문 을 가지 고 코드 와 관련 자 료 를 뒤 져 보기 시작 했다. 
modCount:

           ,modCount              ,      add  remove       

expectedModCount:

             ,       ,               ,
         modCount    ,
               :   ArrayList        ,
              ,        remove  ,        remove              

remove 소스 코드 및 관련 방법 찾기
   //ArrayList:523-538
   public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

    //ArrayList:544-551
    private void fastRemove(int index) {
        modCount++;
        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
    }

코드 를 통 해 reove 방법 이 실제 적 으로 fast Remove 방법 을 호출 한 것 을 볼 수 있 습 니 다.fast Remove 에서 우리 가 관심 을 가 지 는 modCount 에 대해 우리 가 예상 하 는 추가 작업 을 했 습 니 다.그러나 이것 은 다른 관련 값 expected ModCount 의 조작 을 보지 못 했 습 니 다.즉,modCount 는 reove 후에 1 로 변 했 지만 expected ModCount 는 초기 화 된 0 입 니 다.다음 교체 시 이들 은 같 지 않 습 니 다.이상 을 던지다
4)의외로 마지막 두 번 째 요 소 를 삭제 할 때 정상적으로 작 동 하 는 것 을 발견 했다?
코드 와 자 료 를 오랫동안 찾 아 보고 개인 이 이해 하 는 원인,핵심 코드 를 찾 았 습 니 다.
       //ArrayList:853:855
       public boolean hasNext() {
            return cursor != size;
        }

cursor 는 현재 교체 되 는 위 치 를 말 합 니 다.size 는 현재 집합 크기 를 말 합 니 다.hasNext 방법 은 집합 하여 교체 가 완료 되 었 는 지 여 부 를 판단 하 는 표지 입 니 다.이 방법 은 우리 가 이미 잘 알 고 있 습 니 다.마지막 두 번 째 요 소 를 삭제 할 때, cursor 는 length-1 의 위 치 를 가리 키 고 하나의 요 소 를 삭제 한 집합 size 도 length-1 이다.우연 한 일치 로 교체 종 료 를 추진 하여 삭제 에 성공 한 가상 이 생 겼 다.
5)왜 Iterator 가 정상적으로 작 동 합 니까?
같은 방법 으로 Iterator 의 reove 방법 을 찾 습 니 다: 
      //ArrayList:870-883
       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();
            }
        }

핵심 한 마디 발견:expected ModCount=modCount
이로써 샤 오 백 은 오늘 임 무 를 완수 했다^^

좋은 웹페이지 즐겨찾기