2010-09-15 23 views
5

Tengo una clase Polygon en la que deseo implementar dos iteradores: uno para ejecutar todos los elementos (vértices y bordes en orden alterno) solo UNA VEZ, y otro para ejecutarlos ad infinitum (cíclicamente).Java para cada uno, pero múltiples tipos de iteradores?

Desde el punto de vista del uso de cada uno, supongo que solo podré tener uno de los anteriores como el iterador predeterminado que se puede usar con cada uno, mediante la implementación de Iterable.iterator(). ¿Es esto correcto? ¿O hay alguna forma de que yo pueda usar, cada uno con ambos?

Respuesta

11

Sólo añadir dos métodos de regresar dos iteradores diferentes, una para cada caso:

public Iterable<String> eachOnce() { 
    List<String> allResults = new ArrayList<String>(); 
    // fill list 
    return allResults; 
} 

public Iterable<String> eachCyclic() { 
    return new Iterable<String>() { 

     public Iterator<String> iterator() { 
      return new Iterator<String>() { 

       public boolean hasNext() { 
        return true; 
       } 

       public String next() { 
        // TODO implement 
        return null; 
       } 

       public void remove() { 
        // do nothing 
       } 
      }; 

     } 
    }; 
} 

Esto es sólo un ejemplo de una lista de cadenas, simplemente adaptarse.

En lugar de

for (Polygon p : polygons) { } 

sólo tiene que utilizar

for (Polygon p : polygons.eachOnce()) { } 

o la edición cíclica

+0

Buen GHad, me alegro de haberlo preguntado. Esto mantiene la facilidad de uso de for-each y no rompe la encapsulación para evitar el problema. –

+0

+1 Esto es esencialmente lo mismo que java.util.Map: puede llamar a entrySet(), keySet() o values ​​(), que devuelven varios Iterables. – Avi

3

Una respuesta que creo que es mejor que las ya presentadas es un método que convierte cualquier Iterable en una cíclica uno.

public class IterableUtils { 
    public static class CyclicIterator<T> implements Iterator<T> { 
    private final Iterable<T> inner; 
    private Iterator<T> currentIter; 
    public CyclicIterator(Iterable<T> inner) { 
     this.inner = inner; 
    } 
    public boolean hasNext() { 
     if (currentIter == null || !currentIter.hasNext()) { 
     currentIter = inner.iterator(); 
     } 
     return currentIter.hasNext(); 
    } 
    public T next() { 
     if (currentIter == null || !currentIter.hasNext()) { 
     currentIter = inner.iterator(); 
     } 
     return currentIter.next(); 
    } 
    public void remove() { 
     currentIter.remove(); 
    } 
    } 
    public static <T> Iterable<T> cycle(final Iterable<T> i) { 
    return new Iterable<T>() { 
     public Iterator<T> iterator() { return new CyclicIterator<T>(i); } 
    }; 
    } 
} 

A continuación, puede simplemente poner en práctica el método iterador solo en la clase Polygon y utilizar

for (Element e: polygon) { 
    ... 
} 

para repetir una vez

para (elemento E: ciclo (polígono)) { . .. }

para iterar sin fin. Como beneficio adicional, el modificador de ciclo se puede aplicar a cualquier iterable.

+0

Una buena alternativa, Geoff. Puedo usar esto en el futuro. –

Cuestiones relacionadas