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 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 fiddle for it.
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
ListIterator was designed to behave this way. See the conversation beneath ShyJ's answer for the rationale.
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:
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()
.