2011-03-29 69 views
9
  1. IObjectTest是具有 单个布尔测试(对象o)一个接口方法如何实现这个FilteringIterator?

  2. FilteringIterator是迭代器是 与另一迭代 和IObjectTest实例来初始化的实现:新 FilteringIterator(myIterator, myTest)。您的FilteringIterator将 然后允许遍历 'myIterator',但跳过未通过 'myTest'测试的任何 对象。

自“hasNext”操作实际上涉及屡移动底层迭代器 ,直到到达下一个匹配的项目。问题是如何将迭代器移回迭代器,因为hasNext不应该移动基础迭代器。

+1

我已经标记这个“功课”,因为措辞使得它听起来很像是。莱昂,如果不是,请纠正我! – 2011-03-29 15:32:30

+0

是的,是的。谢谢! – Leon 2011-03-29 17:13:11

回答

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 
} 
9

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

谢谢。这正是我所期待的。 – 2014-09-12 07:16:24

+1

嗨Roel,任何好理由remove()不能被支持? – Zeiga 2014-09-14 16:40:03

+0

不,所以我更新了代码,将remove调用委托给支持迭代器。好决定! – 2014-09-15 08:20:01

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(); 
} 

}