2011-03-29 14 views
9
  1. IObjectTest es un método de interfaz con un sola prueba booleana (Object o)¿Cómo implementar este FilteringIterator?

  2. FilteringIterator es una implementación del iterador que es inicializado con otra Iterator y una instancia IObjectTest: nuevo FilteringIterator (myIterator, myTest). Su FilteringIterator mostrará y luego permitirá la iteración sobre 'myIterator', pero omitirá cualquier objeto que no pase la prueba 'myTest'.

Desde la operación "hasNext" realmente implican repeatly mover el iterador subyacente hasta el alcanzar el siguiente elemento coincidente. La pregunta es cómo puede mover su iterador hacia atrás ya que se supone que hasNext no mueve el iterador subyacente.

+1

me ha etiquetado esta "tarea" porque el texto hace que se parece mucho a lo que es. Leon, por favor corrígeme si no es así. –

+0

sí, lo es. ¡Gracias! – Leon

Respuesta

5

Necesitará hacer que su iterador tenga estado. Guarde en caché el último valor que haya obtenido de hasNext y utilícelo del método next, si existe.

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

Si quiere hacerlo usted mismo, puede usar un código similar al que he escrito a continuación. Sin embargo, yo recomiendo uso de 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

gracias. Esto es exactamente lo que estaba buscando. –

+1

Hola Roel, ¿hay alguna buena razón para eliminar() no se admite? – Zeiga

+0

No, así que actualicé el código para delegar la llamada de eliminación al iterador de respaldo. ¡Buena llamada! –

0

¿qué tal mi versión? el método next() podría ser un poco fácil de entender en comparación con los ejemplos anteriores.

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

}