【问题标题】:How to implement this FilteringIterator?如何实现这个 FilteringIterator?
【发布时间】:2011-07-25 09:32:42
【问题描述】:
  1. IObjectTest 是一个具有 单布尔测试(Object o)方法

  2. FilteringIterator 是 Iterator 的一个实现,它是 用另一个迭代器初始化 和一个 IObjectTest 实例:new FilteringIterator(myIterator, 我的测试)。您的 FilteringIterator 将 然后允许迭代 'myIterator',但跳过任何 不通过的对象 'myTest' 测试。

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

【问题讨论】:

  • 我已经标记了这个“作业”,因为它的措辞使它听起来很像。 Leon,如果不是,请纠正我!

标签: java iterator


【解决方案1】:

如果您想自己做,可以使用类似于我在下面编写的代码。不过,我建议你使用 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);
}

【讨论】:

  • 不,所以我更新了代码以将删除调用委托给支持迭代器。好电话!
  • 我很确定remove 方法不起作用。它将删除下一个元素,而不是当前元素。
【解决方案2】:

您需要使您的迭代器有状态。缓存您从 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
}

【讨论】:

    【解决方案3】:

    如果这是家庭作业,这对您没有帮助,但如果不是:Guava Library 具有您所追求的确切功能

    Iterators.filter(Iterator, Predicate)

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

    【讨论】:

      【解决方案4】:

      我的版本怎么样?与前面的示例相比,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();
      }
      

      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-28
        相关资源
        最近更新 更多