Java 链表的自定义迭代器
Java custom iterator for linked list
对于uni我们应该自己实现一个String链表的迭代器。但是关于如何做到这一点的信息非常小。所以我们自己尝试并用谷歌搜索了很多,但我们发现的所有解释都不包括整个代码,我也不知道如何正确实现迭代器。我认为只要我们使用 for each 循环来使用迭代器,一切都可以正常工作,但是一旦我们尝试使用“while (iterator.hasnext) { next }”,它就会停留在第一个元素中链表。我想我知道这个问题是基于我们总是实例化一个新的迭代器,但我不知道如何实现它。希望有人能帮忙,我真的不知道该怎么办,我什么都试过了..
import java.util.Iterator;
import java.util.NoSuchElementException;
public class LinkedList implements Iterable<String> {
// ---------- Attributes ----------
private int size = 0;
private Node head = null;
// private Iterator<String> linkedListIterator = this.iterator(); // ??
static class Node {
// ---------- Attributes ----------
private String object;
private Node next;
// ---------- Constructors ----------
public Node(String object, Node node) {
this.object = object;
this.next = node;
}
public Node() {
this(null, null);
}
// ---------- Getter, Setter ----------
public String getElement() {
return this.object;
}
public void setElement(String object) {
this.object = object;
}
public Node getNext() {
return this.next;
}
public void setNext(Node node) {
this.next = node;
}
}
class LinkedListIterator implements Iterator<String> {
// ---------- Attributes ----------
private Node currentNode = null;
private int counter = 0;
// ---------- Constructor ----------
public LinkedListIterator(LinkedList linkedList) {
this.currentNode = linkedList.head;
}
// ---------- Getter, Setter, Methods ----------
public boolean hasNext() {
return this.currentNode != null;
}
public String next() {
if (!this.hasNext()) {
System.out.println("Fehler: ");
throw new NoSuchElementException();
}
String object = this.currentNode.getElement(); // ?
this.currentNode = this.currentNode.getNext();
this.counter++;
return object;
}
public int getCounter() {
return this.counter;
}
}
// ---------- Getter, Setter, Methods ----------
public Node getHead() {
return this.head;
}
public void addFirst(String object) {
// new node as head
Node newNode = new Node(object, this.head);
this.head = newNode;
this.size++;
}
public String getFirst() { //throws ListEmptyException {
if (isEmpty()) {
// throw new ListEmptyException();
}
return this.head.getElement();
}
public String removeFirst() { //throws ListEmptyException {
if (isEmpty()) {
// throw new ListEmptyException();
}
String object = this.head.getElement();
this.head = this.head.getNext();
return object;
}
public boolean isEmpty() {
return this.head == null;
}
public int getSize() {
return this.size;
}
@Override
public Iterator<String> iterator() {
System.out.println("helo");
return new LinkedListIterator(this);
}
public String toString() {
String output = "";
// this is working:
// for (String element: this) {
// output += element + "\n";
// }
while (this.iterator().hasNext()) {
System.out.println(this.iterator().hasNext());
output += this.iterator().next() + "\n";
}
return output;
}
public static void main(String[] args) {
LinkedList ll = new LinkedList();
ll.addFirst("a");
ll.addFirst("b");
ll.addFirst("c");
ll.addFirst("d");
ll.addFirst("e");
System.out.println(ll.toString());
}
}
问题由此解决
但新问题:为什么这样有效
public String toString() {
String output = "";
Iterator<String> iterator = this.iterator();
while (iterator.hasNext()) {
output += it.next() + "\n";
}
return output;
}
但这不是
public class LinkedList implements Iterable<String> {
private Iterator<String> linkedListIterator = this.iterator();
public String toString() {
String output = "";
while (this.linkedListIterator.hasNext()) {
output += this.linkedListIterator.next() + "\n";
}
return output;
}
}
您的 LinkedListIterator 实现是正确的,问题出在 toString() 方法中。
您正在调用 this.iterator() 3 次,因此每次您 return 一个 LinkedListIterator 的新实例。
相反,您只需调用 this.interator() 一次并使用您获得的实例。
像这样:
Iterator<String> it=this.iterator();
while (it.hasNext()) {
System.out.println(it.hasNext());
output += it.next() + "\n";
}
关于新问题。
如果在 class 的主体中实例化 private Iterator<String> linkedListIterator
属性,(这是永远不应该做的事情),每次引用它时都会调用 public Iterator<String> iterator()
方法并且您将获得 LinkedListIterator
的新实例。
你犯了和一开始一样的错误。
这是为什么只应在方法声明中实例化属性的示例。
请记住,迭代器只能向前移动,如果要重新启动它,则必须创建一个新实例。这就是您通过调用 this.iterator()
所做的事情。
我建议你使用一些调试工具,这样你就可以看到执行的指令
此外,还有一种处理迭代器的设计模式。
https://en.wikipedia.org/wiki/Iterator_pattern
对于uni我们应该自己实现一个String链表的迭代器。但是关于如何做到这一点的信息非常小。所以我们自己尝试并用谷歌搜索了很多,但我们发现的所有解释都不包括整个代码,我也不知道如何正确实现迭代器。我认为只要我们使用 for each 循环来使用迭代器,一切都可以正常工作,但是一旦我们尝试使用“while (iterator.hasnext) { next }”,它就会停留在第一个元素中链表。我想我知道这个问题是基于我们总是实例化一个新的迭代器,但我不知道如何实现它。希望有人能帮忙,我真的不知道该怎么办,我什么都试过了..
import java.util.Iterator;
import java.util.NoSuchElementException;
public class LinkedList implements Iterable<String> {
// ---------- Attributes ----------
private int size = 0;
private Node head = null;
// private Iterator<String> linkedListIterator = this.iterator(); // ??
static class Node {
// ---------- Attributes ----------
private String object;
private Node next;
// ---------- Constructors ----------
public Node(String object, Node node) {
this.object = object;
this.next = node;
}
public Node() {
this(null, null);
}
// ---------- Getter, Setter ----------
public String getElement() {
return this.object;
}
public void setElement(String object) {
this.object = object;
}
public Node getNext() {
return this.next;
}
public void setNext(Node node) {
this.next = node;
}
}
class LinkedListIterator implements Iterator<String> {
// ---------- Attributes ----------
private Node currentNode = null;
private int counter = 0;
// ---------- Constructor ----------
public LinkedListIterator(LinkedList linkedList) {
this.currentNode = linkedList.head;
}
// ---------- Getter, Setter, Methods ----------
public boolean hasNext() {
return this.currentNode != null;
}
public String next() {
if (!this.hasNext()) {
System.out.println("Fehler: ");
throw new NoSuchElementException();
}
String object = this.currentNode.getElement(); // ?
this.currentNode = this.currentNode.getNext();
this.counter++;
return object;
}
public int getCounter() {
return this.counter;
}
}
// ---------- Getter, Setter, Methods ----------
public Node getHead() {
return this.head;
}
public void addFirst(String object) {
// new node as head
Node newNode = new Node(object, this.head);
this.head = newNode;
this.size++;
}
public String getFirst() { //throws ListEmptyException {
if (isEmpty()) {
// throw new ListEmptyException();
}
return this.head.getElement();
}
public String removeFirst() { //throws ListEmptyException {
if (isEmpty()) {
// throw new ListEmptyException();
}
String object = this.head.getElement();
this.head = this.head.getNext();
return object;
}
public boolean isEmpty() {
return this.head == null;
}
public int getSize() {
return this.size;
}
@Override
public Iterator<String> iterator() {
System.out.println("helo");
return new LinkedListIterator(this);
}
public String toString() {
String output = "";
// this is working:
// for (String element: this) {
// output += element + "\n";
// }
while (this.iterator().hasNext()) {
System.out.println(this.iterator().hasNext());
output += this.iterator().next() + "\n";
}
return output;
}
public static void main(String[] args) {
LinkedList ll = new LinkedList();
ll.addFirst("a");
ll.addFirst("b");
ll.addFirst("c");
ll.addFirst("d");
ll.addFirst("e");
System.out.println(ll.toString());
}
}
问题由此解决
但新问题:为什么这样有效
public String toString() {
String output = "";
Iterator<String> iterator = this.iterator();
while (iterator.hasNext()) {
output += it.next() + "\n";
}
return output;
}
但这不是
public class LinkedList implements Iterable<String> {
private Iterator<String> linkedListIterator = this.iterator();
public String toString() {
String output = "";
while (this.linkedListIterator.hasNext()) {
output += this.linkedListIterator.next() + "\n";
}
return output;
}
}
您的 LinkedListIterator 实现是正确的,问题出在 toString() 方法中。 您正在调用 this.iterator() 3 次,因此每次您 return 一个 LinkedListIterator 的新实例。 相反,您只需调用 this.interator() 一次并使用您获得的实例。 像这样:
Iterator<String> it=this.iterator();
while (it.hasNext()) {
System.out.println(it.hasNext());
output += it.next() + "\n";
}
关于新问题。
如果在 class 的主体中实例化 private Iterator<String> linkedListIterator
属性,(这是永远不应该做的事情),每次引用它时都会调用 public Iterator<String> iterator()
方法并且您将获得 LinkedListIterator
的新实例。
你犯了和一开始一样的错误。
这是为什么只应在方法声明中实例化属性的示例。
请记住,迭代器只能向前移动,如果要重新启动它,则必须创建一个新实例。这就是您通过调用 this.iterator()
所做的事情。
我建议你使用一些调试工具,这样你就可以看到执行的指令
此外,还有一种处理迭代器的设计模式。
https://en.wikipedia.org/wiki/Iterator_pattern