What is the best approach for having some kind of lazy iterator where the return is evaluated only on request?

StackOverflow https://stackoverflow.com/questions/1632396

  •  06-07-2019
  •  | 
  •  

Question

import java.util.Collection;

import example.Event;

public interface Query
{
    public boolean hasMore ();

    public Collection<Event> getNext ( long count ) throws Exception;
}

This is the interface I have, which I want to implement.

The implementation is supposed to be like this:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import example.Event;
import example.Query;

public class ListQuery implements Query {

    public ListQuery(List<Event> events, String filter)
            throws FilterParseException {
        // events is the list of given events
        // filter is a string representation of the filter to apply
    }

    public Collection<Event> getNext(long count) throws Exception {
         // returns max. count next entries which match given filter
    }

    public boolean hasMore() {
        // returns if there are more elements matching the given filter
    }
}

What I'm thinking about, is the relationship between hasMore() and getNext(). In both cases I have to evaluate if the filter matches an element of the list. Possibly I don't know the implementation of the given list, so it could be an expensive operation. Obviously I cant just use hasNext() from an iterator, because I have to check if the Event matches the given criteria. In my current implementation I have two different iterators and the current position, where the one for hasMore() is moved up if the position of the iterator for getNext() is larger than the one for hasMore().

What I actually would like to do, is to clone the current iterator which I in turn would use for hasMore(), but this is not possible obviously.

Is there a more elegant solution for this problem?

Was it helpful?

Solution

In your getNext implementation, after you assign your return value, you could advance your iterator until you find an appropriate event. This way, your hasMore can safely test hasNext on your iterator to determine whether to return true or false.

OTHER TIPS

Stop torturing yourself :-) and just use this:

Iterables.filter(Iterable, Predicate)

It takes care of these problems for you.

If you don't have your data in anything Iterable, only an Iterator, see the corresponding class Iterators. If you need to implement the Iterator yourself, it may help to extend AbstractIterator in that same package.

Then if you really want to be able to retrieve chunks of results you can use the partition() method of the Itera*s classes.

I am thinking you don't even need two iterators. The hasMore call can iterate all the way until it finds a match and just stay there (if the element that it already points to matches, don't iterate). Now the getNext will use same iterator to iterate and populate return collection until either count is reached or no more matching elements are found.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top