java 迭代器接口
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15365165/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
The Iterator interface
提问by Henrik Hillestad L?vold
I have a University assignement that requires me to implement an inner class which implements the Iterator interface. The iterator works on a single-linked list superclass.
我有一个大学作业,它要求我实现一个实现 Iterator 接口的内部类。迭代器在单链表超类上工作。
Currently my inner class looks like this:
目前我的内部类看起来像这样:
private class ListIterator implements Iterator<V>{
Node temp;
boolean nextCalled = false;
ListIterator(Node fo){
this.temp = fo;
}
@Override
public boolean hasNext() {
if(temp != null){
return true;
}
return false;
}
@Override
public V next() {
nextCalled = true;
return temp.getReprValue();
}
@Override
public void remove() {
if(nextCalled && hasNext()){
nextCalled = false;
removeElement(temp.getReprKey());
temp = temp.getNext();
}
}
}
Now my problem is that the hasNext() method returns true even when the list is actually empty. Everything else seems to work. I have probably overlooked a logic flaw somewhere, but I cannot find it myself.
现在我的问题是,即使列表实际上为空,hasNext() 方法也会返回 true。其他一切似乎都有效。我可能在某处忽略了一个逻辑缺陷,但我自己找不到。
采纳答案by Caesar Ralf
Changed your implementation to reflect what the Iterator contract needs. You need to remember that you need to be able to iterate over all elements of the collection, i.e., next()
should start from the first element and after every call it must change the current next element to the next element in the list or throw an exception if there's none.
更改您的实现以反映迭代器合同的需求。您需要记住,您需要能够遍历集合的所有元素,即,next()
应该从第一个元素开始,并且在每次调用之后,它必须将当前的下一个元素更改为列表中的下一个元素,或者在以下情况下抛出异常没有。
It's good to read the Iterator interface docto undestand the way you need to implement it and start from there.
阅读Iterator 接口文档以了解实现它所需的方式并从那里开始是很好的。
private class ListIterator implements Iterator<V> {
private Node next;
private boolean alreadyDeleted = false;
ListIterator(Node node){
this.next = node;
}
@Override
public boolean hasNext() {
// because next is the current element. We need to iterate over all the elements
// from the collection.
return next != null;
}
@Override
public V next() {
if (next == null) {
throw new NoSuchElementException();
}
Node current = next;
this.next = current.getNext();
this.alreadyDeleted = false; // it's better to try to elimate this state variable. You can try to do in another way, if yours removeElement returns something
return current;
}
@Override
public void remove() {
if (alreadyDeleted || next == null) {
throw new IllegalStateException();
}
removeElement(next.getReprKey());
this.alreadyRemoved = true;
}
}
回答by Frank
You need to keep track of where you are in your list, implement a cursor
, or if your nodes in the linked list are aware of their next
, just ask them if they have a next element.
When the cursor is bigger then the length / your node has no next
you return false in hasNext().
您需要跟踪您在列表中的位置,实现 a cursor
,或者如果链表中的节点知道它们的next
,只需询问它们是否有下一个元素。当光标大于长度/您的节点没有时,next
您在 hasNext() 中返回 false。
Do all this in your hasNext()
method. Remember, it's okay to have next() throw an exception if hasNext()
would have been false - so you need to make sure that's the only time it will throw an exception.
在您的hasNext()
方法中执行所有这些操作。请记住,如果 next() 为hasNext()
false,则可以抛出异常- 因此您需要确保这是唯一一次抛出异常。
As I don't know the underlying data structure of your list, I can't tell you which one of these will be better.
由于我不知道您列表的底层数据结构,因此我无法告诉您其中哪一个会更好。
回答by Edwin Buck
To reduce some code, and make it a touch more readable
减少一些代码,使其更具可读性
- rename
temp
tonext
, - use shortcut notation,
- probably should have some concept of the
current
node,
- 重命名
temp
为next
, - 使用快捷符号,
- 大概应该有
current
节点的一些概念,
which makes the update look like:
这使得更新看起来像:
private Node next;
private Node current; //track deletion
@Override
public boolean hasNext() {
return next != null;
}
public Node getNext() {
if (hasNext()) {
current = next;
next = next.getNextNode();
}
return current;
}
the delete could set current to null. We don't need a flag (assuming that we're fine with doing nothing if a person deletes prior to calling the first getNext()
. Heck, if we really want to go for the gold, have remove()
throw an IllegalStateException
if current == null
.
删除可以将当前设置为空。我们不需要标志(假设如果一个人在调用第一个之前删除了我们什么都不做就可以了getNext()
。哎呀,如果我们真的想获得金牌,就remove()
抛出一个IllegalStateException
if current == null
。
回答by Javier
hasNext
returns true if the current node (temp
) is not null
.
hasNext
如果当前节点 ( temp
) 不是,则返回 true null
。
If your linked list implementation uses a header node, then the constructor always receives fo!=null
and hasNext
will return true
even though the list is empty. You should consider this fact in your implementation.
如果你的链接列表实现使用头节点,则构造函数总是接收fo!=null
和hasNext
返回true
,即使该列表是空的。你应该在你的实现中考虑这个事实。
Based on your code, it seem that
根据您的代码,似乎
ListIterator(Node fo){
this.temp = fo.getNext();
}
may do the trick (if header.getNext()==null
for an empty list).
可能会起作用(如果header.getNext()==null
是空列表)。