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().t开发者_高级运维oLowerCase().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 few reasons:
- It would make a typical1
Iterator
object bigger; i.e. an extra field to hold the current object. - It would mean 1 extra 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 currentIterator
design. - There is the issue of the Iterator "hanging onto" the current object. In some cases that will prevent from being GC'ed.
- The large majority of iterator use-cases don't require a current object.
Also, there are other ways to deal with this.
Sounds like a good call ...
1 - This and other points don't apply equally to all implementations of the Iterator
API. Indeed, in some cases the implementation of current()
will be simple. But that is beside the point. Unless you make the proposed current()
method an optional2 method (like remove()
) every iterator implementation ... and by extension, every Map
and Collection
class ... has to provide this functionality, and deal with the issues, one way or another.
2 - Optional methods come with their own problems.
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
精彩评论