JDK에서 제공하는 반복 인터페이스를 사용하여 Java 컬렉션을 반복하는 경우가 많습니다.
Iterator iterator = list.iterator(); while(iterator.hasNext()){ String string = iterator.next(); //do something }
사실 반복을 순회라고 간단히 이해할 수 있는데, 이는 다양한 컨테이너의 모든 객체를 순회하기 위한 표준화된 메소드 클래스입니다. 매우 전형적인 디자인 패턴입니다. Iterator 패턴은 컬렉션 클래스를 반복하기 위한 표준 액세스 방법입니다. 다양한 유형의 컬렉션 클래스에서 액세스 논리를 추상화하여 컬렉션의 내부 구조가 클라이언트에 노출되는 것을 방지할 수 있습니다. 이것이 반복자가 없을 때 수행하는 방법입니다.
배열의 경우 첨자를 사용하여 처리합니다.
int[] arrays = new int[10]; for(int i = 0 ; i < arrays.length ; i++){ int a = arrays[i]; //do something }
ArrayList의 경우 처리 방법은 다음과 같습니다.
List<String> list = new ArrayList<String>(); for(int i = 0 ; i < list.size() ; i++){ String string = list.get(i); //do something }
두 가지 방법 모두 사전에 컬렉션의 내부 구조를 알고 있습니다. 액세스 코드와 컬렉션 자체는 긴밀하게 결합되어 있으며 액세스 로직은 컬렉션 클래스와 클라이언트 코드에서 분리될 수 없습니다. 동시에 각 컬렉션은 순회 방법에 해당하며 클라이언트 코드는 재사용할 수 없습니다. 실제 적용에서는 위의 두 세트를 통합하는 것이 상당히 번거롭습니다. 그래서 위의 문제를 해결하기 위해 항상 동일한 논리를 사용하여 컬렉션을 탐색하는 Iterator 모드가 탄생했습니다. 이렇게 하면 클라이언트 자체가 컬렉션의 내부 구조를 유지할 필요가 없으며 모든 내부 상태는 Iterator에 의해 유지됩니다. 클라이언트는 컬렉션 클래스를 직접 처리하지 않으며 항상 Iterator를 제어하고 "forward", "backward" 및 "get the current element" 명령을 보내 전체 컬렉션을 간접적으로 탐색합니다.
위는 Iterator 패턴에 대한 간략한 설명일 뿐이며, Java의 Iterator 인터페이스를 살펴보고 어떻게 구현되는지 살펴보겠습니다.
1. java.util.Iterator
Java에서 Iterator는 반복에 대한 기본 규칙만 제공하며, 다음과 같이 정의됩니다. : 컬렉션을 반복하는 반복자입니다. 반복자는 Java 컬렉션 프레임워크의 열거를 대체합니다. 반복자와 열거형 사이에는 두 가지 차이점이 있습니다.
1. 반복자를 사용하면 호출자가 잘 정의된 의미 체계를 사용하여 반복 중에 반복자가 가리키는 컬렉션에서 요소를 제거할 수 있습니다.
2. 메소드명이 개선되었습니다.
인터페이스는 다음과 같이 정의됩니다.
public interface Iterator { boolean hasNext(); Object next(); void remove(); }
그 중
Object next(): 요소를 반환합니다. 반복자 참조와 교차하면 반환 값은 Object이며 필요한 유형으로 캐스팅되어야 합니다.
boolean hasNext(): 컨테이너에 액세스 가능한 요소가 있는지 확인
void Remove(): 반복자가 방금 교차한 요소를 삭제합니다.
우리의 경우 일반적으로 반복을 완료하려면 next() 및 hasNext() 메서드만 사용해야 합니다.
for(Iterator it = c.iterator(); it.hasNext(); ) { Object o = it.next(); //do something }
앞서 설명했듯이 Iterator에는 큰 장점이 있습니다. 즉, 컬렉션의 내부 구조와 상태를 알 필요가 없습니다. 특정 내부 구현에 대해서는 hasNext() 및 next()를 통해 Iterator에 의해 유지 관리됩니다. 그러나 자격을 갖춘 프로그래머로서 우리는 Iterator의 구현을 알아내는 것이 매우 필요합니다. ArrayList의 소스코드를 분석해 보겠습니다.
2. 각 컬렉션의 Iterator 구현
다음은 ArrayList의 Iterator 구현을 분석한 것입니다. 실제로 ArrayList의 데이터 구조를 이해하면 다음과 같습니다. , Hashset 및 TreeSet, 내부 구현을 통해 Iterator를 구현하는 방법에 대한 좋은 아이디어도 갖게 됩니다. ArrayList의 내부 구현은 배열을 사용하기 때문에 해당 위치의 인덱스만 기록하면 되며 메서드 구현도 비교적 간단합니다.
2.1. ArrayList의 Iterator 구현
ArrayList에서는 먼저 Iterator 인터페이스를 구현하는 내부 클래스 Itr을 다음과 같이 정의합니다.
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 및 ExpectModCount)가 정의되어 있습니다. 커서가 다음 요소의 인덱스 위치를 나타내는 경우 lastRet는 이전 요소의 인덱스 위치를 나타냅니다.
int cursor; int lastRet = -1; int expectedModCount = modCount;
커서와 lastRet의 정의에서 lastRet가 항상 1 작다는 것을 알 수 있습니다. 커서보다 커서 hasNext() 구현 방법은 매우 간단합니다. 커서와 lastRet가 동일한지 확인하기만 하면 됩니다.
public boolean hasNext() { return cursor != size; }
next()의 구현은 실제로 비교적 간단합니다. 커서 인덱스 위치에서 요소를 반환한 다음 커서와 lastRet를 수정하면 됩니다. 🎜>
checkForComodification() 主要用来判断集合的修改次数是否合法,即用来判断遍历过程中集合是否被修改过。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(); } }
以上所述是小编给大家介绍的Java集合Iterator迭代的实现方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对PHP中文网的支持!
更多Java集合Iterator迭代的实现方法相关文章请关注PHP中文网!