📜  Java|实现迭代器和可迭代接口

📅  最后修改于: 2022-05-13 01:55:48.012000             🧑  作者: Mango

Java|实现迭代器和可迭代接口

Java中的 Collection 框架中使用迭代器来逐个检索元素。与此相关的更多详细信息和介绍,请参见此链接。

为什么需要实现Iterable接口?

每个适当实现 Iterable 接口的类,都可以在增强的 For 循环(for-each 循环)中使用。在设计自定义数据结构时需要实现 Iterator 接口。
例子:

for(Item item: customDataStructure) {
    // do stuff
}

如何实现Iterable接口?

为了实现一个可迭代的数据结构,我们需要:

  1. 在所述数据结构中实现 Iterable 接口及其方法
  2. 创建一个实现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 类的内部类来实现,因为它不会在其他地方使用。

  1. next() 和 hasNext() 是如何工作的?
    要实现迭代器,我们需要一个光标或指针来跟踪我们当前所在的元素。根据底层数据结构,我们可以从一个元素前进到另一个元素。这是在 next() 方法中完成的,该方法返回当前元素并且光标前进到下一个元素。
    在推进指针之前,我们检查下一个元素是否存在。即我们可以将幕后代码描绘如下:
    While(iterator.hasNext()) { //if next element exists
        next(); // advance the pointer
    }
    
  2. 初始化光标
    游标初始化完全取决于数据结构。例如,在链表中,我们会将光标初始化为头元素。在数组列表中,我们会将光标初始化为第 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