Java|实现迭代器和可迭代接口
Java中的 Collection 框架中使用迭代器来逐个检索元素。与此相关的更多详细信息和介绍,请参见此链接。
为什么需要实现Iterable接口?
每个适当实现 Iterable 接口的类,都可以在增强的 For 循环(for-each 循环)中使用。在设计自定义数据结构时需要实现 Iterator 接口。
例子:
for(Item item: customDataStructure) {
// do stuff
}
如何实现Iterable接口?
为了实现一个可迭代的数据结构,我们需要:
- 在所述数据结构中实现 Iterable 接口及其方法
- 创建一个实现Iterator接口和相应方法的Iterator类。
我们可以将伪代码概括如下:
class CustomDataStructure implements Iterable<> {
// code for data structure
public Iterator<> iterator() {
return new CustomIterator<>(this);
}
}
class CustomIterator<> implements Iterator<> {
// constructor
CustomIterator<>(CustomDataStructure obj) {
// initialize cursor
}
// Checks if the next element exists
public boolean hasNext() {
}
// moves the cursor/iterator to next element
public T next() {
}
// Used to remove an element. Implement only if needed
public void remove() {
// Default throws UnsupportedOperationException.
}
}
注意:Iterator 类也可以作为 Data Structure 类的内部类来实现,因为它不会在其他地方使用。
- next() 和 hasNext() 是如何工作的?
要实现迭代器,我们需要一个光标或指针来跟踪我们当前所在的元素。根据底层数据结构,我们可以从一个元素前进到另一个元素。这是在 next() 方法中完成的,该方法返回当前元素并且光标前进到下一个元素。
在推进指针之前,我们检查下一个元素是否存在。即我们可以将幕后代码描绘如下:While(iterator.hasNext()) { //if next element exists next(); // advance the pointer }
- 初始化光标
游标初始化完全取决于数据结构。例如,在链表中,我们会将光标初始化为头元素。在数组列表中,我们会将光标初始化为第 0 个元素。
从执行的角度来看:- 如果 Iterator 类被实现为内部类,我们可以简单地使用“this”关键字(例如 cursor = CustomDataStructure.this.element)来访问所需的元素
- 如果 Iterator 类被实现为一个单独的类,我们可以将数据结构的这个对象传递给 iterator 类的构造函数,如下例所示。
下面的程序说明了Iterable接口的使用:
下面给出了一个使用泛型的自定义链接列表。链表由 Node 对象组成,这些对象包含一个通用数据值和指向下一个节点的指针。该类提供了一些标准的“get”方法,如 getHead() 和 getTail(),以及必要的 Iterator()函数,该函数必须在实现 Iterable 接口时实现。
然后创建必要的自定义类“ListIterator”,它将实现 Iterator 接口,随之而来的是 hasNext() 和 next() 的功能也将被实现。这两个函数构成了Iterable和Iterator接口的核心。
import java.util.Iterator;
// Custom Linked List class using Generics
class List implements Iterable {
Node head, tail;
// add new Element at tail of the linked list in O(1)
public void add(T data)
{
Node node = new Node<>(data, null);
if (head == null)
tail = head = node;
else {
tail.setNext(node);
tail = node;
}
}
// return Head
public Node getHead()
{
return head;
}
// return Tail
public Node getTail()
{
return tail;
}
// return Iterator instance
public Iterator iterator()
{
return new ListIterator(this);
}
}
class ListIterator implements Iterator {
Node current;
// initialize pointer to head of the list for iteration
public ListIterator(List list)
{
current = list.getHead();
}
// returns false if next element does not exist
public boolean hasNext()
{
return current != null;
}
// return current data and update pointer
public T next()
{
T data = current.getData();
current = current.getNext();
return data;
}
// implement if needed
public void remove()
{
throw new UnsupportedOperationException();
}
}
// Constituent Node of Linked List
class Node {
T data;
Node next;
public Node(T data, Node next)
{
this.data = data;
this.next = next;
}
// Setter getter methods for Data and Next Pointer
public void setData(T data)
{
this.data = data;
}
public void setNext(Node next)
{
this.next = next;
}
public T getData()
{
return data;
}
public Node getNext()
{
return next;
}
}
// Driver class
class Main {
public static void main(String[] args)
{
// Create Linked List
List myList = new List<>();
// Add Elements
myList.add("abc");
myList.add("mno");
myList.add("pqr");
myList.add("xyz");
// Iterate through the list using For Each Loop
for (String string : myList)
System.out.println(string);
}
}
输出:
abc
mno
pqr
xyz