Как мне обратиться к текущему объекту в итераторе - PullRequest
26 голосов
/ 02 марта 2011

Я пытаюсь реализовать метод поиска в TreeSet.Используя итератор с условным условием, я хотел бы иметь возможность пробежаться по множеству и напечатать объект, соответствующий условию.Однако способ, которым я сейчас занимаюсь, это распечатка последующего объекта, а не текущего.Это то, что я имею до сих пор:

public void getDetails() {
        Iterator<Person> it = this.getPersonSet().iterator();
        System.out.println("Enter First Name");
        String first = in.next().toLowerCase();
        System.out.println("Enter Second Name");
        String last = in.next().toLowerCase();

        while (it.hasNext()) {
            if (it.next().getLast().toLowerCase().equals(last)) {
                Person p = it.next();
                System.out.println(p);
            }
        }

    }

Любая помощь будет отличной

Ответы [ 5 ]

33 голосов
/ 02 марта 2011

Это то, что вы хотели бы сделать:

while (it.hasNext()) {
            Person p = it.next();
            if (p.getLast().toLowerCase().equals(last)) {
                System.out.println(p);
            }
        }
22 голосов
/ 02 марта 2011

Как обратиться к текущему объекту в итераторе

Для записи API Iterator не позволяет вам это делать.Нет понятия «текущий» объект.Метод Iterator.next() дает вам следующий объект ... и движется дальше.

(Методы ListIterator.previous() и ListIterator.next() аналогичны. Обратите внимание, что в случае ListIterator поведение метода задокументировано в виде курсора, который обозначает позицию до / между / после элементов в последовательностиповторяется.)

Решение состоит в том, чтобы присвоить результат вызова it.next() временной переменной, как описано в принятом ответе.


Не знаю точнопочему разработчики не включили понятие «текущий» объект в API, но я могу подумать о нескольких причинах:

  • Это сделало бы типичный объект итератора больше;т. е. дополнительное поле для хранения текущего объекта.
  • Это означало бы, что еще один метод для реализации класса Iterator должен быть реализован.
  • Понятие текущего объекта плохо согласуется с «курсором»."модель, задокументированная в интерфейсе ListIterator ... и подразумеваемая текущим дизайном Iterator.
  • Существует небольшая проблема, связанная с тем, что Iterator" зависает "на текущем объекте, тем самым не давая ему быть GC'ed.
  • В подавляющем большинстве случаев использования итераторов не требуется текущий объект.
  • Существуют и другие способы решения этой проблемы.

Звучиткак хороший звонок ...

3 голосов
/ 01 февраля 2017

Если вам нужна существующая реализация, вы можете использовать ее из Google Guava или Apache Commons Collections .
Другие ответы проще для вашей простой задачи, но есливам нужно обойти итератор и отследить последний элемент, возвращаемый функцией next (), это поможет.

Вот пример использования Guava с кодом OP (предполагая, что Person действительно имеет String toLowerCase() метод):

import com.google.common.collect.PeekingIterator;
import static com.google.common.collect.Iterators.peekingIterator;

public void getDetails() {
    PeekingIterator<Person> it = peekingIterator(this.getPersonSet().iterator());
    System.out.println("Enter First Name");
    String first = in.next().toLowerCase();
    System.out.println("Enter Second Name");
    String last = in.next().toLowerCase();

    while (it.hasNext()) {
        // note the usage of peek() instead of next()
        if (it.peek().getLast().toLowerCase().equals(last)) {
            Person p = it.next();
            System.out.println(p);
        }
    }

}
1 голос
/ 02 марта 2011

Удерживайте ссылку на объект в отдельной переменной:

Person current = it.next();
current.methodOne();
current.methodTwo();

Когда вы закончите с текущим значением, повторите его следующим

...
// done? 
current = it.next();

Впетля выглядит так:

while( it.hasNext() ) { 
   Person current = it.next();
   current.doA();
   current.doB();
   current.doC();
 }
0 голосов
/ 02 мая 2019

метод next () возвращает текущий объект, например:

private class IterSinglyLinked implements SimpleIterator<T> {
    Element curr = head;        // next element to return

    public boolean hasNext() {
        return curr != null;
    }

    public T next() throws Exception {
        if (curr == null) throw new Exception("no more elements");
        T data = curr.data;
        curr = curr.next;
        return data;
    }
}

Если он вернет следующий, а не текущий, он не сможет добраться до самого первого

...