Java 可迭代的数据类型
《算法(第四版)》1.3 节在介绍背包、队列和栈时,顺便介绍了一下 Java 迭代。下面简单总结其相关内容。
对于许多应用场景,用例的要求只是用某种方式处理集合中的每个元素,或者叫做迭代访问集合中的所有元素。比如有时候,我们迭代访问数组中的所有元素,将其依次打印出来。
为迭代数组,我们可以用 for(int i = 0; i < a.length; i++) {}
也可以用 foreach 语句 for(int i : a) {}
。
能不能让我们自己定义的数据类型也支持 foreach 迭代?
比如现在有一个自定义栈 ResizingArrayStack。如何让它支持以下操作?
ResizingArrayStack collection = new ResizingArrayStack();
for (String s : collection)
System.out.println(s);
其实,foreach 语句只是 while 语句的一种简写方式。它本质上和以下 while 语句是等价的:
Iterator i = collection.iterator();
while (i.hasNext())
{
String s = i.next();
System.out.println(s);
}
所以,要支持 foreach 迭代:
? 首先,ResizingArrayStack 必须实现一个 iterator() 方法,该方法返回一个 Iterator 对象;
? 其次,其支持的 iterator() 方法返回的 Iterator 对象必须支持两个方法:hasNext()(返回一个布尔值,用来判断是否还有下一个迭代元素)和 next()(返回 ResizingArrayStack 中的下一个迭代元素)。
Java 使用接口机制来指定一个类所必须实现的方法,要使 ResizingArrayStack 类可迭代,第一步就是让它实现 Iterable 接口,要实现 Iterable,先要在 ResizingArrayStack 类声明中加入 implements Iterable
:
public class ResizingArrayStack- implements Iterable
- {
...
}
然后在类中添加一个 iterator() 方法用来返回一个迭代器 Iterator
public Iterator- iterator()
{ return new ResizingArrayStackIterator(); }
迭代器是一个实现了 hasNext() 和 next() 方法的类的对象,类似地,通过实现 Iterator 接口来约定 ResizingArrayStackIterator 类必须实现这两个方法,同时我们根据数据类型的迭代要求写好 hasNext() 和 next() 中的迭代逻辑:
private class ResizingArrayStackIterator implements Iterator-
{
...
public boolean hasNext() { ... }
public Item next() { ... }
}
最后,Iterator 接口不在 java.lang 中,需要用 import java.util.Iterator;
将其导入。
所以一个实现了迭代的 ResizingArrayStackIterator 类应该是这样:
import java.util.Iterator;
public class ResizingArrayStack- implements Iterable
-
{
...
public Iterator
- iterator()
{ return new ResizingArrayStackIterator(); }
private class ResizingArrayStackIterator implements Iterator
-
{
...
public boolean hasNext() { ... }
public Item next() { ... }
}
}
另,Iterator 接口中还有一个 remove() 方法,只需要实现 foreach 迭代来访问数据的话不需要实现该方法。