如何实现这个FilteringIterator?

时间:2011-03-29 15:20:43

标签: java iterator

  1. IObjectTest是一个带有的接口 单布尔测试(Object o)方法

  2. FilteringIterator是Iterator的一个实现         用另一个迭代器初始化         和一个IObjectTest实例:new         FilteringIterator(myIterator,         MYTEST)。你的FilteringIterator会         然后允许迭代         'myIterator',但跳过任何         没有通过的物体         'myTest'测试。

  3. 由于“hasNext”操作实际上涉及重复移动底层迭代器 直到下一个匹配的项目。问题是如何将it迭代器移回迭代器,因为hasNext不应该移动底层迭代器。

4 个答案:

答案 0 :(得分:10)

如果您想自己动手,可以使用类似于我在下面编写的代码。但是,我建议您使用Guava的Iterators.filter(Iterator, Predicate)

public class FilteredIterator<T> implements Iterator<T> {
    private Iterator<? extends T> iterator;
    private Filter<T> filter;
    private T nextElement;
    private boolean hasNext;

    /**
     * Creates a new FilteredIterator using wrapping the iterator and returning only elements matching the filter.
     * 
     * @param iterator
     *            the iterator to wrap
     * @param filter
     *            elements must match this filter to be returned
     */
    public FilteredIterator(Iterator<? extends T> iterator, Filter<T> filter) {
        this.iterator = iterator;
        this.filter = filter;

        nextMatch();
    }

    @Override
    public boolean hasNext() {
        return hasNext;
    }

    @Override
    public T next() {
        if (!hasNext) {
            throw new NoSuchElementException();
        }

        return nextMatch();
    }

    private T nextMatch() {
        T oldMatch = nextElement;

        while (iterator.hasNext()) {
            T o = iterator.next();

            if (filter.matches(o)) {
                hasNext = true;
                nextElement = o;

                return oldMatch;
            }
        }

        hasNext = false;

        return oldMatch;
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }
}

public interface Filter<T> {

    /**
     * Determines whether elements should be filtered or not.
     * 
     * @param element the element to be matched against the filter
     * @return {@code true} if the element matches the filter, otherwise {@code false}
     */
    public boolean matches(T element);
}

答案 1 :(得分:5)

您需要使迭代器具有状态。缓存从hasNext检索到的最后一个值,并使用next方法中的值(如果存在)。

private boolean hasCached;
private T cached;

public boolean hasNext() {
   if ( hasCached ) return true;
   //iterate until you find one and set hasCached and cached
}

public T next() {
   if ( hasCached ) {
      hasCached = false;
      return cached;
   }
   //iterate until next matches
}

答案 2 :(得分:4)

如果这是作业,这对你没有帮助,但如果没有:Guava Library具有你以后的确切功能

Iterators.filter(Iterator, Predicate)

(您可以查看how they did it获取灵感)

答案 3 :(得分:0)

我的版本怎么样?与前面的例子相比,next()方法可能有点容易理解。

public class PredicateIterator implements Iterator {

private Iterator iterator;
private Predicate predicate;
private Object cached;
private boolean hasNextCached;
private boolean hasNext;

public PredicateIterator(Iterator iterator, Predicate predicate) {
    this.iterator = iterator;
    this.predicate = predicate;
}

@Override
public boolean hasNext() {
    if (hasNextCached) {
        return hasNext;
    } else {
        return findNextMatch();
    }
}

private boolean findNextMatch() {
    boolean match = false;
    while(!match && iterator.hasNext()) {
        cached = iterator.next();
        match = predicate.test(cached);
    }
    hasNextCached = true;
    hasNext = match;
    return match;
}

@Override
public Object next() {
    if (hasNext()) {
        hasNextCached = false;
        return cached;
    } else {
        throw new NoSuchElementException();
    }
}

@Override
public void remove() {
    iterator.remove();
}

}