2010-09-15 19 views
5

Ich habe eine Klasse Polygon, auf der ich zwei Iteratoren implementieren möchte: einen durch alle Elemente (Ecken und Kanten in alternierender Reihenfolge) nur einmal durchlaufen, und ein anderes durch sie ad infinitum (zyklisch) durchlaufen.Java für jeden, aber mehrere Iterator-Typen?

Von einem für jeden Verwendungszweck, meine Annahme ist, dass ich nur in der Lage sein, eine der oben genannten der Standard-Iterator, der mit for-each, über die Implementierung von Iterable.iterator() verwendet werden kann. Ist das richtig? Oder gibt es einen Weg, den ich für beide nutzen könnte?

Antwort

11

Fügen Sie einfach zwei Methoden zwei verschiedene Iteratoren, für jeden Fall einer Rückkehr:

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

     } 
    }; 
} 

Dieses mit einer Liste von Strings ist nur ein Beispiel, nur anpassen.

Statt

for (Polygon p : polygons) { } 

verwenden nur

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

oder die zyklische Ausgabe

+0

Nice one GHad, ich bin froh, dass ich gefragt habe. Dies hält die Benutzerfreundlichkeit von for-each aufrecht und verhindert nicht die Kapselung, um das Problem zu umgehen. –

+0

+1 Dies ist im Wesentlichen das gleiche wie was java.util.Map tut - Sie können entrySet(), keySet() oder values ​​() aufrufen, die alle verschiedene Iterables zurückgeben. – Avi

3

Eine Antwort, die ich denke, ist besser als die bereits vorgestellten ist ein Verfahren, das jede Iterable in einem zyklischen dreht ein.

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

Dann können Sie einfach die einzelnen Iteratormethode in der Polygon-Klasse implementieren und verwenden

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

einmal zu durchlaufen und

für (Element e: Zyklus (Polygon)) { . .. }

um endlos zu iterieren. Als Bonus kann der Zyklusmodifikator auf jedes iterierbare Element angewendet werden.

+0

Eine nette Alternative, Geoff. Ich kann das in Zukunft verwenden. –

Verwandte Themen