使用 ListIterator 在 Java 中的 LinkedList 上来回移动
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13483035/
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
Using ListIterator to move back and forth over a LinkedList in Java
提问by Kurt Koller
I have a LinkedList over which I need to iterate back and forth multiple times. I am using it to keep track of a series of pages in a workflow that will be created dynamically. This does not behave as I would expect. Given this example:
我有一个 LinkedList,我需要在它上面来回迭代多次。我使用它来跟踪将动态创建的工作流中的一系列页面。这不像我期望的那样表现。鉴于这个例子:
LinkedList<String> navigationCases;
navigationCases.add("page1");
navigationCases.add("page2");
navigationCases.add("page3");
navigationCases.add("page4");
ListIterator navigationItr = navigationCases.listIterator();
navigationItr.next(); // Returns page1
navigationItr.next(); // Returns page2
navigationItr.previous(); //Returns page2 again
navigationItr.next(); //Returns page2 again
I thought perhaps I was building my list incorrectly, or using the Iterator wrong, but after reading the documentation, this seems to be by design:
我想也许我是在错误地构建我的列表,或者错误地使用了迭代器,但是在阅读了文档之后,这似乎是设计使然:
A ListIterator has no current element; its cursor position always lies between the element that would be returned by a call to previous() and the element that would be returned by a call to next().
ListIterator 没有当前元素;它的光标位置始终位于调用 previous() 返回的元素和调用 next() 返回的元素之间。
And:
和:
(Next) Returns the next element in the list. This method may be called repeatedly to iterate through the list, or intermixed with calls to previous to go back and forth. (Note that alternating calls to next and previous will return the same element repeatedly.)
(Next) 返回列表中的下一个元素。该方法可能会被重复调用以遍历列表,或者与对前一个的调用混合来回。(请注意,交替调用 next 和 previous 将重复返回相同的元素。)
So after reading this, it is clear why my code is behaving the way it does. I just don't understand why it should work this way. Even remove seems to be bending over backwards to accommodate this implementation:
因此,阅读本文后,很清楚为什么我的代码的行为方式如此。我只是不明白为什么它应该这样工作。甚至 remove 似乎也在向后弯曲以适应这种实现:
Note that the remove() and set(Object) methods are not defined in terms of the cursor position; they are defined to operate on the last element returned by a call to next() or previous().
请注意,remove() 和 set(Object) 方法不是根据光标位置定义的;它们被定义为对调用 next() 或 previous() 返回的最后一个元素进行操作。
Conceptually, a LinkedList seemed to model my workflow cases pretty well, but I can't use an Iterator that behaves this way. Am I missing something here, or should I just write my own class maintain a list of cases and navigate through them?
从概念上讲,LinkedList 似乎很好地模拟了我的工作流程案例,但我不能使用具有这种行为的 Iterator。我在这里遗漏了什么,还是应该编写自己的类来维护案例列表并浏览它们?
采纳答案by ShyJ
This should do your job:
这应该可以完成您的工作:
public class Main {
public static void main(String[] args) {
final LinkedList<String> list = new LinkedList<String> ();
list.add ("1"); list.add ("2"); list.add ("3"); list.add ("4");
final MyIterator<String> it = new MyIterator (list.listIterator());
System.out.println(it.next());
System.out.println(it.next ());
System.out.println(it.next ());
System.out.println(it.previous ());
System.out.println(it.previous ());
System.out.println(it.next ());
}
public static class MyIterator<T> {
private final ListIterator<T> listIterator;
private boolean nextWasCalled = false;
private boolean previousWasCalled = false;
public MyIterator(ListIterator<T> listIterator) {
this.listIterator = listIterator;
}
public T next() {
nextWasCalled = true;
if (previousWasCalled) {
previousWasCalled = false;
listIterator.next ();
}
return listIterator.next ();
}
public T previous() {
if (nextWasCalled) {
listIterator.previous();
nextWasCalled = false;
}
previousWasCalled = true;
return listIterator.previous();
}
}
}
And a fiddlefor it.
和一个小提琴。
回答by Paul Lammertsma
ListIterator was designed to behave this way. See the conversation beneath ShyJ's answer for the rationale.
ListIterator 被设计为以这种方式运行。请参阅 ShyJ 回答下方的对话以了解理由。
I find this behavior to be beyond idiotic, and have instead written a very simple alternative. Here's the Kotlin code with a extension function for ArrayLists:
我发现这种行为超出了愚蠢的范围,而是编写了一个非常简单的替代方案。这是带有 ArrayLists 扩展函数的 Kotlin 代码:
class ListIterator<E>(var list: ArrayList<E>) : Iterator<E> {
private var cursor: Int = 0
fun replace(newList: ArrayList<E>) {
list = newList
cursor = 0
}
override fun hasNext(): Boolean {
return cursor + 1 < list.size
}
override fun next(): E {
cursor++
return current()
}
fun hasPrevious(): Boolean {
return 0 <= cursor - 1
}
fun previous(): E {
cursor--
return current()
}
fun current(): E {
return list[cursor]
}
}
fun <E> ArrayList<E>.listFlippingIterator() = ListIterator(this)
If you wish to include removal functionality, I highly recommend writing the API to explicitly instruct the iterator if it should remove left or right, e.g. by defining those methods as removeNext()
and removePrevious()
.
如果您希望包含删除功能,我强烈建议编写 API 以明确指示迭代器是否应该删除左或右,例如通过将这些方法定义为removeNext()
and removePrevious()
。
回答by Madbreaks
Do something like this (pseudocode) --
做这样的事情(伪代码)-
class SkipIterator extends ListIterator {
public E previous(){
E n = super.previous();
return super.previous();
}
...
}
then:
然后:
LinkedList<String> navigationCases;
navigationCases.add("page1");
navigationCases.add("page2");
navigationCases.add("page3");
navigationCases.add("page4");
SkipIterator navigationItr = (SkipIterator)navigationCases.listIterator();
navigationItr.next(); // Returns page1
navigationItr.next(); // Returns page2
navigationItr.previous(); // Returns page1
Cheers
干杯