ListIterator, повторяющий элементы при альтернативных вызовах next() и previous()

Я написал приведенную ниже программу для итерации в списке, но при альтернативном обходе next() and previous() он повторяет элемент. Я знаю исправление, поставив индикатор и используя его для extra next и extra previous до моей логики печати. Но я хочу знать, почему такое поведение и каков алгоритм работы итератора.

Я уже проверил javaDoc, и там написано так:

следующий
Возвращает следующий элемент в списке. Этот метод может вызываться неоднократно для перебора списка или смешиваться с вызовами предыдущего для перехода вперед и назад. (Обратите внимание, что при чередовании вызовов следующего и предыдущего элементов будет неоднократно возвращаться один и тот же элемент.)

но вопрос почему? и какова логика или цель этого?

public class IterateLinkedListUsingListIterator {

public static void main(String[] args) throws NumberFormatException,
        IOException {
    LinkedList lList = new LinkedList();

    lList.add("1");
    lList.add("2");
    lList.add("3");
    lList.add("4");
    lList.add("5");

    ListIterator itr = lList.listIterator();
    boolean ch = true;

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    while (ch) {
        System.out.println("Enter choice");
        int chi = Integer.parseInt(br.readLine());
        switch (chi) {
        case 1:
            if (itr.hasNext()) {
                System.out.println(itr.next());
            }
            break;
        case 2:

            if (itr.hasPrevious()) {
                System.out.println(itr.previous());
            }
            break;

        default:
            ch = false;
        }

    }

}

}

согласно ответу @vincrichaud и указателю java doc курсор указывает между элементом, а не на элементе, почему это так? есть ли какая-то конкретная причина для этого.

                     Element(0)   Element(1)   Element(2)   ... Element(n-1)
cursor positions:  ^            ^            ^            ^                  ^

person Rishal dev singh    schedule 23.03.2018    source источник
comment
Это резонный вопрос. ListIterators немного странные и почти никогда не используются. Чтобы понять их, нужно представить текущую позицию как находящуюся между двумя элементами. Когда вы вызываете next(), вы перешагиваете элемент справа от вас (и возвращаете его). Когда вы можете выполнить команду previous(), вы перешагиваете через элемент слева (и возвращаете его). Это может показаться странным, но это именно так.   -  person cpp beginner    schedule 23.03.2018
comment
Это как многократно прыгать влево и вправо через один и тот же объект. Объект, через который вы перепрыгиваете, никогда не меняется. Если вы хотите, чтобы объект, через который перепрыгнули, изменился, вам нужно дважды перепрыгнуть в одном и том же направлении.   -  person cpp beginner    schedule 23.03.2018


Ответы (1)


Как описано в документе.

Далее Возвращает следующий элемент в списке и перемещает курсор вперед.

Предыдущий Возвращает предыдущий элемент в списке и перемещает позицию курсора назад.

Что не очевидно, так это то, что позиция курсора всегда находится между элементом, а не на элементе. Это также описано в доке.

ListIterator не имеет текущего элемента; его позиция курсора всегда лежит между элементом

Зная это, совершенно очевидно, что при альтернативном вызове next() и previous() вы получите один и тот же элемент.

LinkedList lList = new LinkedList();
lList.add("1");
lList.add("2");
lList.add("3");
lList.add("4");
lList.add("5");
//lList look like [1,2,3,4,5]
ListIterator itr = lList.listIterator(); //create iterator at position before element 0

itr.next() // return the next element => so return "1"
           // And advance the cursor position => position between element 0 and element 1

itr.previous(); // return the previous element => so return "1"
           // And step back the cursor position => position before element 0
person vincrichaud    schedule 23.03.2018
comment
Хорошо, согласно вашему ответу, теперь поведение в порядке, но почему курсор помещается между элементами, а не на элементы. - person Rishal dev singh; 23.03.2018
comment
Понятия не имею. Спросите Оракула. Я думаю, это потому, что так поступать логичнее. Курсор указывает, какой элемент вы уже прошли, а какой нет. В противном случае указанный элемент не будет ни уже увиденным, ни еще не увиденным. Также, если функция указывающего элемента, такая как next и previous, должна быть getElementAndMoveForward и getElementAndMoveBackward, что, я думаю, менее удобно для пользователя. - person vincrichaud; 23.03.2018