2011-03-29 68 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(); 
} 

}