简体   繁体   中英

How do I refer to the current object in an iterator

I am trying to implement a search method in a TreeSet. By using an iterator with a condtional I would like to be able to run through the set and print the object that matches the condition. However the way I am doing it at the moment is printing out the subsequent object rather than the current. This is what I have so far:

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);
            }
        }

    }

Any help would be great

This is what you would want to do:

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

How do I refer to the current object in an iterator

For the record, the Iterator API does not allow you to do this. There is no notion of a "current" object. The Iterator.next() method gives you the next object ... and moves on.

(The ListIterator.previous() and ListIterator.next() methods are analogous. Note that in the ListIterator case, method behaviour is documented in terms of a cursor that denotes a position before / between / after elements in the sequence being iterated.)

The solution is to assign the result of calling it.next() to a temporary variable, as described by the accepted answer.


I don't know for sure why the designers didn't include the notion of a "current" object in the API, but I can think of a couple of reasons:

  • It would make a typical iterator object bigger; ie an extra field to hold the current object.
  • It would mean more 1 more method for an Iterator class to implement.
  • The notion of a current object does not fit well with the "cursor" model documented in the ListIterator interface ... and implied by the current Iterator design.
  • There is a minor issue of the Iterator "hanging onto" the current object, thereby preventing it from being GC'ed.
  • The large majority of iterator use-cases don't require a current object.
  • There are other ways to deal with this.

Sounds like a good call ...

If you need an existing implementation, you can use the ones from Google Guava or Apache Commons Collections .
The other answers are easier for your simple problem, but if you need to pass the iterator around and keep track of the last item returned by next(), these would help.

Here is an example using Guava with the OP's code (assumging Person indeed has a String toLowerCase() method):

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);
        }
    }

}

Hold the reference of the object in a separate var:

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

When you're done with the current value, re-assing it the next

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

In a loop looks like:

while( it.hasNext() ) { 
   Person current = it.next();
   current.doA();
   current.doB();
   current.doC();
 }

the next() method returns the current object, like this:

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;
    }
}

If it returns the next one rather than the current one, there will be no way to reach the very first one

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM