2010-09-15 5 views
5

J'ai une classe Polygon sur laquelle je souhaite implémenter deux itérateurs: un pour parcourir tous les éléments (sommets et arêtes en alternance) juste une FOIS, et un autre pour les parcourir à l'infini (cycliquement). D'un point de vue d'utilisation pour chaque utilisation, je suppose que je ne pourrai avoir que l'un des éléments ci-dessus qui soit l'itérateur par défaut pouvant être utilisé pour chacun, via l'implémentation de Iterable.iterator(). Est-ce correct? Ou y a-t-il un moyen que je pourrais utiliser pour chacun des deux?Java pour chacun, mais plusieurs types d'itérateurs?

Répondre

11

Il suffit d'ajouter deux méthodes retourner deux itérateurs différentes, une pour chaque cas:

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

     } 
    }; 
} 

Ceci est juste un exemple avec une liste de chaînes, juste adapter.

Au lieu de

for (Polygon p : polygons) { } 

il suffit d'utiliser

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

ou l'édition cyclique

+0

Un bon GHad, je suis content d'avoir demandé. Cela conserve la facilité d'utilisation de chacun et ne rompt pas l'encapsulation pour contourner le problème. –

+0

+1 Ceci est essentiellement la même chose que java.util.Map - vous pouvez appeler entrySet(), keySet() ou values ​​(), qui renvoient tous des Iterables. – Avi

3

Une réponse que je pense est mieux que ceux qui ont déjà présenté est une méthode qui transforme tout Iterable en un cyclique un.

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

Ensuite, vous pouvez simplement mettre en œuvre la méthode iterator unique dans la classe Polygon et utiliser

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

pour itérer une fois

pour (élément e: Cycle (polygone)) { . .. }

pour itérer indéfiniment. En prime, le modificateur de cycle peut être appliqué à n'importe quel itérable.

+0

Une belle alternative, Geoff. Je peux l'utiliser à l'avenir. –

Questions connexes