Почему list-iterator.next(); не возвращается к текущей позиции элемента, если только он не повторяется несколько раз до конца?

Согласно документации Java:

ListIterator не имеет текущего элемента; его позиция курсора всегда находится между элементом, который будет возвращен вызовом предыдущей(), и элементом, который будет возвращен вызовом следующей(). Итератор для списка длины n имеет n+1 возможных позиций курсора, как показано символами вставки (^) ниже:

Мой вопрос, например, предположим, что цикл while выполняется, и при нажатии 2 я вызываю метод

public void callNextElement(int choice, LinkedList<String> linkedList) {

    ListIterator<String> listIterator = linkedList.listIterator();
    if (choice == 2) {
        if (listIterator.hasNext()){
            listIterator.next();
            System.out.println("We have: " + listIterator.next());
        }
    }
}

Теперь это напечатает первый элемент и вернется к циклу while для ввода, теперь снова нажав 2, я получу первый элемент/запись списка. И если бы я сделал:

System.out.println("We have: " + listIterator.next());
System.out.println("We have: " + listIterator.next());
System.out.println("We have: " + listIterator.next());
System.out.println("We have: " + listIterator.next());
....

Это напечатает другие элементы в связанном списке

Итак, мои вопросы:

  1. Почему он не распечатывает 2-й элемент и так далее в методе, который я вызвал?

  2. Почему это работает только, если listiterator.next() вызывается последовательно, как я сделал, напечатав их выше?

  3. Что произойдет, если listiterator на самом деле сохранит позицию следующего элемента, чтобы при вызове next() (без последовательности) он печатал следующий элемент? Не первый.

РЕДАКТИРОВАТЬ:

Я чувствую себя таким глупым, но это сборка мусора Java работает в моем вызове метода? Если да, то имеет смысл, почему он каждый раз печатает 1-й элемент. Я новичок в Java и совершенно забыл об этом...


person calculusnoob    schedule 04.09.2018    source источник
comment
Повторное редактирование: нет, это не имеет ничего общего со сборкой мусора. Это связано только с тем, что каждый linkedList.listIterator() создает новый итератор списка со своей собственной информацией о позиции (в этом случае это будет начало списка, поэтому каждый next() в отдельных новых итераторах списка приведет к первому элемент - при условии, что список не пуст).   -  person Pshemo    schedule 04.09.2018


Ответы (2)


Каждый итератор списка имеет свою независимую позицию в списке. Каждый раз, когда вы вызываете listIterator(), вы получаете новый итератор, который начинается с начала списка.

ListIterator<String> listIterator = linkedList.listIterator();

Если вы хотите перебирать последовательные элементы, вам нужно вызвать listIterator() один раз и сохранить итератор где-нибудь, чтобы его можно было использовать повторно.

person John Kugelman    schedule 04.09.2018

Чтобы ответить на ваши вопросы, вы должны понимать, что Iterator помнит свою позицию в Collection или Iterable, но только тот же самый экземпляр Iterator знает эту позицию (т.е. сколько раз Iterator.next() был вызван)

1) Почему он не распечатывает 2-й элемент и т. д. в методе, который я вызвал?

ListIterator<String> listIterator = linkedList.listIterator();

В этой строке вашего метода вы создаете новый Iterator для списка каждый раз, когда вы вызываете этот метод. Новый Iterator всегда будет начинаться с начала списка. Вот почему вы всегда будете получать только первый элемент списка.

2) Почему это работает только в том случае, если listiterator.next() вызывается последовательно? как я сделал, напечатав их выше.

Как упоминалось выше, новый итератор всегда будет начинаться с (или, правильнее сказать, раньше) первого элемента списка. Вызывая Iterator.next(), вы перемещаете итератор к следующему элементу списка. Если вы вызовете next() несколько раз для одного и того же Iterator, вы будете перемещаться по всему списку, пока Iterator.hasNext() не вернет false. Если Iterator.hasNext() равно false и вы продолжаете звонить Iterator.next(), будет выброшено NoSuchElementException.

3) Что произойдет, если listiterator на самом деле сохранит позицию следующего элемента, чтобы при вызове next() (без последовательности) он печатал следующий элемент? Не первый.

Я думаю, что это уже ответили выше?!

Вы можете изменить свой метод, чтобы принимать в качестве аргумента сам Iterator вместо списка, например:

public void callNextElement(int choice, ListIterator<String> listIterator) {
    if (choice == 2) {
        if (listIterator.hasNext()){
            listIterator.next()
            System.out.println("We have: " + listIterator.next());
        }
    }
}

Этот метод будет называться так:

ListIterator<String> listIterator = linkedList.listIterator();
while (condition == true) {
    callNextElement(choice, listIterator);
}

Таким образом, вы всегда будете передавать одно и то же Iterator в метод callNextElement и последовательно продвигать позицию этого итератора.

И нет, это не имеет абсолютно никакого отношения к сбору мусора.

person dpr    schedule 04.09.2018