Итерация списка до тех пор, пока список не станет пустым

Я пытаюсь повторить список, при этом на каждой итерации я делаю одно из следующих действий:

  • Перейти к следующему элементу (по некоторой логике)
  • Удаление текущего элемента

Что мне нужно, так это то, что после того, как я переберу все элементы, он будет продолжать повторяться до тех пор, пока список не станет пустым (логика гарантирует, что все элементы будут удалены).

Проблема в том, что после того, как итератор перебирает все элементы списка, он не продолжает работать с элементами, которые я не удалил:

List<Integer> lst = new ArrayList();
lst.add(1);
lst.add(2);
lst.add(3);

Iteartor<Integer> iterator = lst.listIterator();
while (iterator.hasNext()){
    Integer curInt = iterator.next();
    if (!passTest(curInt)){
        continue;
    }
    iterator.remove();
}

ВАЖНОЕ ПРИМЕЧАНИЕ: passTest(curInt) логика может быть разной для каждой итерации. Это означает, что первая итерация может вызвать continue, тогда вторая и третья итерации вызовут удаление. ПРОБЛЕМА в том, что я ожидаю четвертую итерацию (по первому элементу, который не был удален).

Решение, которое я нашел:

List<Integer> lst = new ArrayList();
lst.add(1);
lst.add(2);
lst.add(3);

Iteartor<Integer> iterator = lst.listIterator();
while (!lst.isEmpty()){

    Integer curInt;
    if (iteration.hasNext()){
        curInt = iterator.next();
    } else {
        curInt = lst.get(0);
    }

    if (!passTest(curInt)){
        continue;
    }

    iterator.remove();
}

Это правильный способ добиться этого?


person Roni Koren Kurtberg    schedule 29.08.2019    source источник


Ответы (1)


Ваше решение не кажется правильным. Сначала вы переберете все элементы List, возможно, удалив некоторые из них. Как только вы закончите перебирать List, iteration.hasNext() всегда будет возвращать false, поэтому вы продолжите получать первый элемент (из-за curInt = lst.get(0)). Если вы удалите этот первый элемент, вы получите другой элемент при следующем выполнении curInt = lst.get(0), поэтому List в конце станет пустым, но это не похоже на желаемое поведение (если это было желаемое поведение, вы можно исключить Iterator и просто продолжать получать первый элемент в цикле и, возможно, удалять его).

Вы должны использовать вложенные циклы и воссоздать экземпляр Iterator внутри внешнего цикла:

while (!lst.isEmpty()) {
    Iteartor<Integer> iterator = lst.listIterator();
    while (iterator.hasNext()) {
        Integer curInt = iterator.next();
        if (passTest(curInt)) {
            iterator.remove();
        }
    }
}

Каждая итерация внешнего цикла создает Iterator и выполняет внутренний цикл.

Каждая итерация внутреннего цикла перебирает элементы List и, возможно, удаляет некоторые из них.

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

person Eran    schedule 29.08.2019