Iterator
约 451 字大约 2 分钟
2024-08-08
Java 的集合类都可以使用 for each 循环,List、Set 和 Queue 会迭代每个元素,Map 会迭代每个 key
使用迭代器的好处在于,调用方总是以统一的方式遍历各种集合类型,而不必关系它们内部的存储结构
List 为例
List<String> list = List.of("Apple", "Orange", "Pear");
for (String s : list) {
System.out.println(s);
}实际上,Java 编译器并不知道如何遍历 List。上述代码能够编译通过,只是因为编译器把 for each 循环通过 Iterator 改写为了普通的 for 循环
for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
String s = it.next();
System.out.println(s);
}我们把这种通过 Iterator 对象遍历集合的模式称为迭代器
栗子
如果我们自己编写了一个集合类,想要使用 for each 循环,只需满足以下条件
集合类实现
Iterable接口,该接口要求返回一个Iterator对象用
Iterator对象迭代集合内部数据
我们实现一个以倒序遍历的集合 ReverseList
public static void main(String[] args) {
ReverseList<String> rlist = new ReverseList<>();
rlist.add("Apple");
rlist.add("Orange");
rlist.add("Pear");
for (String s : rlist) {
System.out.println(s);
}
// Pear
// Orange
// Apple
}class ReverseList<T> implements Iterable<T> {
// 持有一个 ArrayList
private List<T> list = new ArrayList<>();
// 直接使用 list 的 add 方法
public void add(T t) {
list.add(t);
}
@Override
public Iterator<T> iterator() {
return new ReverseIterator(list.size());
}
/**
* 使用内部类 ReverseIterator,可以很方便获取外部类的 this 引用
*/
class ReverseIterator implements Iterator<T> {
int index;
ReverseIterator(int index) {
this.index = index;
}
@Override
public boolean hasNext() {
return index > 0;
}
// 从最大下标获取元素
@Override
public T next() {
index--;
return ReverseList.this.list.get(index);
}
}
}在编写 Iterator 的时候,我们通常可以用一个内部类来实现 Iterator 接口,这个内部类可以直接访问对应的外部类的所有字段和方法