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

collectionsiteratorjava

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?

Best Answer

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.

Related Topic