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
接口,这个内部类可以直接访问对应的外部类的所有字段和方法