JDK 용기 클래스 의 교체 기 모드 학습

교체 기 모드 는 커서 모드 라 고도 부 르 는데 용기 안의 요 소 를 방문 하 는 방법 을 제공 하 는 것 이 며 용기 내부 의 실현 을 폭로 하지 않 아 도 된다.
이렇게 하면 두 가지 뚜렷 한 장점 이 있다.
1. 용기 내부 의 구조 가 변화 할 때 교체 기 자체 가 변화 하지 않 으 면 외부 에서 교체 기 를 사용 하 는 업무 코드 는 수정 하지 않 아 도 된다.
2. 만약 에 우리 가 한 가지 이상 의 교체 방식 을 제공 해 야 한다 면 교체 기 를 추가 하고 용기 류 를 수정 하지 않 아 도 된다.
이 두 가지 도 디자인 모델 이 요구 하 는 단일 직책 조례 를 만족 시 키 기 에 딱 좋다.
JDK 용기 류 (Array List 와 LinkedList) 가 사용 하 는 교체 기 모드 를 중점적으로 분석 합 니 다.
JDK 가 제공 하 는 교체 기 인 터 페 이 스 는 다음 과 같 습 니 다.
public interface Iterator<E> {
    boolean hasNext();//        
    E next();//       
    void remove();//    
}

Array List 는 배열 로 구 성 된 List 로 Iterator 로 돌아 가 는 인 터 페 이 스 는 다음 과 같 습 니 다.
public Iterator<E> iterator() {
        return new Itr();//Itr ArrayList   ,       :
}
//  Java     ,               。
private class Itr implements Iterator<E> {
        int cursor;//       
        int lastRet = -1;//               ,-1        
        int expectedModCount = modCount;//             (        )    
        
        //size          ,hasNext               ,   ,         
        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        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;//cursor  1
            return (E) elementData[lastRet = i];//   cursor+1   
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
                checkForComodification();//               ,      ,                 
            try {
                ArrayList.this.remove(lastRet);//       
                cursor = lastRet;//cursor       
                lastRet = -1;//           
                expectedModCount = modCount;//      
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();//        
            }
        }
        //                 
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
}

Array List 는 다음 과 같은 양 방향 교체 기 를 제공 합 니 다.
//       
public ListIterator<E> listIterator(int index) {
     if (index < 0 || index > size)//        
            throw new IndexOutOfBoundsException("Index: "+index);
     return new ListItr(index);
}
private class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            super();
            cursor = index;//      
        }
        //         
        public boolean hasPrevious() {
            return cursor != 0;
        }
        //       
        public int nextIndex() {
            return cursor;
        }
        //         
        public int previousIndex() {
            return cursor - 1;
        }
        //       
        @SuppressWarnings("unchecked")
        public E previous() {
            checkForComodification();//      
            int i = cursor - 1;
            if (i < 0)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i;
            return (E) elementData[lastRet = i];
        }
        //     
        public void set(E e) {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.set(lastRet, e);
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
        //    
        public void add(E e) {
            checkForComodification();

            try {
                int i = cursor;
                ArrayList.this.add(i, e);
                cursor = i + 1;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
 }

LinkedList 는 양 방향 링크 를 데이터 로 하 는 조직 방식 으로 내부 교체 기의 실현 은 Array List 와 유사 하 며 방문 요소 만 옮 겨 다 녀 야 합 니 다.
위의 실현 을 통 해 알 수 있다.
1. 우리 가 사용 할 때 내부 에 어떻게 저장 되 어 있 는 지 모 르 겠 지만 용기 류 의 요 소 를 조작 할 수 있 습 니 다. 내부 배열 의 조직 방식 이 바 뀌 면 정확 한 교체 기 를 제공 하면 프로그램 은 수정 할 필요 가 없습니다.
2. 새로운 교체 기 를 추가 하 는 것 도 편리 하 다. 용기 류 를 수정 할 필요 가 없다. 내부 류 의 방식 은 실현 편의 만 제공 하고 교체 기의 실현 은 완전히 독립 할 수 있다.

좋은 웹페이지 즐겨찾기