>  기사  >  Java  >  자바 개선 장(30) -----반복자

자바 개선 장(30) -----반복자

黄舟
黄舟원래의
2017-02-11 10:14:531158검색

 Java를 사용하는 우리에게는 반복이 낯설지 않습니다. 우리는 Java 컬렉션을 반복하기 위해 JDK에서 제공하는 반복 인터페이스를 자주 사용합니다.

안돼


                                 단순히 반복을 순회로 이해하세요. , 다양한 컨테이너의 모든 객체를 순회하기 위한 표준화된 메소드 클래스입니다. 이는 매우 일반적인 디자인 패턴입니다. 반복자 패턴은 컬렉션 클래스를 순회하기 위한 표준 액세스 방법입니다. 다양한 유형의 컬렉션 클래스에서 액세스 논리를 추상화하여 컬렉션의 내부 구조가 클라이언트에 노출되는 것을 방지할 수 있습니다. 이것이 반복자가 없을 때 수행하는 방법입니다. 다음과 같습니다:

배열의 경우 첨자를 사용하여 처리합니다.

Iterator iterator = list.iterator();
        while(iterator.hasNext()){
            String string = iterator.next();
            //do something
        }


 ArrayList가 처리되는 방식은 다음과 같습니다.

int[] arrays = new int[10];
for(int i = 0 ; i < arrays.length ; i++){
       int a = arrays[i];
       //do something
   }


이 두 가지 방법의 경우 항상 컬렉션의 내부 구조를 미리 알고 있으며, 액세스 코드와 컬렉션 자체가 긴밀하게 결합되어 있어 액세스 로직을 서로 분리할 수 없습니다. 컬렉션 클래스 및 클라이언트 코드와 분리됩니다. 동시에 각 컬렉션은 순회 방법에 해당하며 클라이언트 코드는 재사용할 수 없습니다. 실제 적용에서는 위의 두 세트를 통합하는 것이 상당히 번거롭습니다. 그래서 위의 문제를 해결하기 위해 항상 동일한 논리를 사용하여 컬렉션을 탐색하는 Iterator 모드가 탄생했습니다. 클라이언트 자체는 컬렉션의 내부 구조를 유지할 필요가 없으며 모든 내부 상태는 Iterator에 의해 유지됩니다. 클라이언트는 컬렉션 클래스를 직접 처리하지 않으며 항상 Iterator를 제어하고 "forward", "backward" 및 "get the current element" 명령을 보내 전체 컬렉션을 간접적으로 탐색합니다.

위는 Iterator 모드에 대한 간략한 설명일 뿐이며, Java의 Iterator 인터페이스가 어떻게 구현되는지 살펴보겠습니다.

1. java.util.Iterator

Java에서 Iterator는 반복 작업만 제공하는 인터페이스입니다. 기본 규칙은 JDK에서 다음과 같이 정의됩니다: 컬렉션을 반복하는 반복자. 반복자는 Java 컬렉션 프레임워크의 열거를 대체합니다. 반복자와 열거형 사이에는 두 가지 차이점이 있습니다.

                                                                 ~                                                    요소를 제거합니다.

                                  2. 메소드 이름이 개선되었습니다.

인터페이스는 다음과 같이 정의됩니다.

List<String> list = new ArrayList<String>();
   for(int i = 0 ; i < list.size() ;  i++){
      String string = list.get(i);
      //do something
   }


 위치:

 객체 next(): 방금 교차된 요소에 대한 참조를 반환합니다. 반복자, 반환 값 개체이며 필요한 유형으로 캐스팅되어야 합니다.

                                                      부울 hasNext() 결정: 컨테이너에 접근 가능한 요소가 있는지 여부

void Remove(): 반복자가 방금 지나간 요소를 제거합니다.

우리에게는, 우리만 일반적으로, next()와 hasNext()라는 두 가지 메서드를 사용하여 반복을 완료할 수 있습니다. 다음과 같습니다:

아아아아아아아아아아

        前面阐述了Iterator有一个很大的优点,就是我们不必知道集合的内部结果,集合的内部结构、状态由Iterator来维持,通过统一的方法hasNext()、next()来判断、获取下一个元素,至于具体的内部实现我们就不用关心了。但是作为一个合格的程序员我们非常有必要来弄清楚Iterator的实现。下面就ArrayList的源码进行分析分析。

二、各个集合的Iterator的实现

        下面就ArrayList的Iterator实现来分析,其实如果我们理解了ArrayList、Hashset、TreeSet的数据结构,内部实现,对于他们是如何实现Iterator也会胸有成竹的。因为ArrayList的内部实现采用数组,所以我们只需要记录相应位置的索引即可,其方法的实现比较简单。

2.1、ArrayList的Iterator实现

        在ArrayList内部首先是定义一个内部类Itr,该内部类实现Iterator接口,如下:

private class Itr implements Iterator<E> {
    //do something
}


        而ArrayList的iterator()方法实现:

public Iterator<E> iterator() {
        return new Itr();
    }


        所以通过使用ArrayList.iterator()方法返回的是Itr()内部类,所以现在我们需要关心的就是Itr()内部类的实现:

在Itr内部定义了三个int型的变量:cursor、lastRet、expectedModCount。其中cursor表示下一个元素的索引位置,lastRet表示上一个元素的索引位置

int cursor;             
int lastRet = -1;     
int expectedModCount = modCount;


        从cursor、lastRet定义可以看出,lastRet一直比cursor少一所以hasNext()实现方法异常简单,只需要判断cursor和lastRet是否相等即可。

public boolean hasNext() {
    return cursor != size;
}


        对于next()实现其实也是比较简单的,只要返回cursor索引位置处的元素即可,然后修改cursor、lastRet即可,

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];  //lastRet + 1 且返回cursor处元素
        }


        checkForComodification()主要用来判断集合的修改次数是否合法,即用来判断遍历过程中集合是否被修改过。在java提高篇(二一)-----ArrayList中已经阐述了。modCount用于记录ArrayList集合的修改次数,初始化为0,,每当集合被修改一次(结构上面的修改,内部update不算),如add、remove等方法,modCount + 1,所以如果modCount不变,则表示集合内容没有被修改。该机制主要是用于实现ArrayList集合的快速失败机制,在Java的集合中,较大一部分集合是存在快速失败机制的,这里就不多说,后面会讲到。所以要保证在遍历过程中不出错误,我们就应该保证在遍历过程中不会对集合产生结构上的修改(当然remove方法除外),出现了异常错误,我们就应该认真检查程序是否出错而不是catch后不做处理。

       final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }


        对于remove()方法的是实现,它是调用ArrayList本身的remove()方法删除lastRet位置元素,然后修改modCount即可。

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的Iterator实现讲解到这里,对于Hashset、TreeSet等集合的Iterator实现,各位如果感兴趣可以继续研究,个人认为在研究这些集合的源码之前,有必要对该集合的数据结构有清晰的认识,这样会达到事半功倍的效果!!!!

————————————————————————————————————— ————————————

위는 Java 개선글(3부 10) -- ---Iterator의 내용, 더 많은 관련 내용을 보려면 PHP 중국어 웹사이트(www.php.cn)를 참고하세요!



성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.