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
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
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.
Une belle alternative, Geoff. Je peux l'utiliser à l'avenir. –
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. –
+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