Как реализовать этот FilteringIterator? - PullRequest
9 голосов
/ 29 марта 2011
  1. IObjectTest - это интерфейс с метод одиночного логического теста (объект o)

  2. FilteringIterator - это реализация Iterator, которая инициализируется другим итератором и экземпляр IObjectTest: новый FilteringIterator (myIterator, MyTest). Ваш FilteringIterator будет затем разрешить итерацию myIterator, но пропускает любой объекты, которые не проходят Тест myTest.

Поскольку операция hasNext на самом деле предполагает повторное перемещение базового итератора до достижения следующего соответствующего элемента. Вопрос в том, как он может переместить его итератор назад, поскольку hasNext не должен перемещать основной итератор.

Ответы [ 4 ]

10 голосов
/ 29 марта 2011

Если вы хотите сделать это самостоятельно, вы можете использовать код, подобный тому, что я написал ниже.Тем не менее, я рекомендую вам использовать Guava's 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);
}
5 голосов
/ 29 марта 2011

Вы должны сделать свой итератор с состоянием.Кэшируйте последнее значение, полученное вами из 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
}
4 голосов
/ 29 марта 2011

Если это домашнее задание, это вам не поможет, но если нет: Библиотека гуавы обладает именно теми функциями, которые вам нужны после

Iterators.filter(Iterator, Predicate)

(Вы могли бы взглянуть на как они это сделали для вдохновения)

0 голосов
/ 30 марта 2016

как насчет моей версии?метод 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();
}

}

...