一、Iterator
我们在程序中常见的如:
public static void main(String[] args) {
Integer[] arr = new Integer[10];
for(int i = 0;i< 10;i++){
System.out.println(arr[i]);
}
}
在for循环里面我们的变量i随着循环次数的增加而递增,我们可以通过i的值顺序遍历数组或者有序集合元素。
这就是Iterator模式,Iterator模式用于在数据集合中按照顺序遍历集合(反复做某件事情,也叫迭代器)。如果我们需要使用这个模式:那我们首先需要又一个Iterator接口(含有 next()方法、hasNext()方法),有了Iterator接口那我们自然需要一个Iterator接口的实现类IteratorImpl,比如我们想遍历一个List,那我们需要有一个List(根据泛型List<Integer、String、等等>)类,我们还需要有一个类这个类既实现Iterator接口又含有我们需要遍历的List,在类里面我们实现具体的hasNext和next方法然后对我们的List进行遍历。
下面我们拿Jdk源码说一下:
这个是Iterator接口的源码:
package java.util;
import java.util.function.Consumer;
public interface Iterator<E> {
//如果仍有元素可以迭代,则返回true。
boolean hasNext();
//返回迭代的下一个元素
E next();
//从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
default void remove() {
throw new UnsupportedOperationException("remove");
}
//jdk1.8引入对剩余元素执行action的操作
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
ListIterator源码:
package java.util;
//系列表迭代器,允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。、、ListIterator 没有当前元素;它的光标位置
//始终位于调用 previous() 所返回的元素和调用 next() 所返回的元素之间。长度为 n 的列表的迭代器有 n+1 个可能的指针位置
public interface ListIterator<E> extends Iterator<E> {
// Query Operations
//以正向遍历列表时,如果列表迭代器有多个元素,则返回 true(换句话说,如果 next 返回一个元素而不是抛出异常,则返回 true)。
boolean hasNext();
//返回列表中的下一个元素。
E next();
//如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
boolean hasPrevious();
//返回列表中的前一个元素。
E previous();
//返回对 next 的后续调用所返回元素的索引。
int nextIndex();
返回对 previous 的后续调用所返回元素的索引。
int previousIndex();
// Modification Operations
//从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。
void remove();
用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。
void set(E e);
将指定的元素插入列表(可选操作)。
void add(E e);
}
上面的ListIterator(实现了Iterator)就可以理解为我说的Iterator接口,在JDK的ArrayList中因为ArrayList实现了Iterator接口所以我们也有了实现Iterator接口的实现类,ArrayList本身就是我们需要迭代的集合类,那么我们现在还差一个打通ArrayList和Iterator的类,在这里因为ArrayList实现了Iterator接口,所以ArrayList本身就可以做到将自身的元素在实现Iterator的内部类中就行迭代。代码如下:
private class Itr implements Iterator<E> {
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size();
}
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public E previous() {
checkForComodification();
try {
int i = cursor - 1;
E previous = get(i);
lastRet = cursor = i;
return previous;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor-1;
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.set(lastRet, e);
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
AbstractList.this.add(i, e);
lastRet = -1;
cursor = i + 1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
这样就实现了Iterator模式。
Iterator模式的好处是可以将遍历和实现分离开,其实就是一个Iterator遍历的接口,一个需要遍历的集合接口,不论集合里面是数组集合还是其他集合,我们只需要将集合的具体事例传递给Iterator的实现中进行遍历即可。