Eine Iterator
ist die kleinstmögliche API zum sequentiellen Abarbeiten von Daten, daher abstrahiert sie von der zugrunde liegenden Datenquelle. Da es nur vorwärts gehen kann (next()
), ohne eine Option zum Zurücksetzen oder Zurückspulen, ist es ein Einwegobjekt, das nach der Verwendung weggeworfen werden muss. Und aufgrund der begrenzten API ist es nicht möglich, sie einfach zu "kopieren", ohne die Implementierung und/oder die zugrunde liegende Datenquelle zu kennen.
So gibt es vier Möglichkeiten, um Ihr Problem zu behandeln:
(1) Re-aquire einen neuen Iterator aus der zugrunde liegenden Datenquelle
Gerade getQuestionIterator(File file)
rufen jedes Mal, wenn Sie über die Daten zu durchlaufen müssen (nochmal).
- Vorteil: Einfach zu bedienen, einfach zu implementieren. Kein Cache erforderlich.
- Nachteil: Leistung (z. B. Datei muss erneut gelesen/geparst werden). Die zugrunde liegende Datenquelle wurde möglicherweise in der Zwischenzeit geändert.
(2) Kombinieren aller Verarbeitungscode in eine einzige Schleife Iterieren
Statt ...
while (iterator.hasNext()) { /* first processing step */ }
while (iterator.hasNext()) { /* second processing step */ }
while (iterator.hasNext()) { /* third processing step */ }
...
... kombinieren alle Schritte:
while (iterator.hasNext()) {
String question = iterator.next();
/* first processing step */
/* second processing step */
/* third processing step */
...
}
- Vorteil: Nur ein Iterator erforderlich. Kein Cache erforderlich.
- Nachteil: Nicht immer möglich, z.B. wenn Verarbeitungsschritte Abhängigkeiten haben.
(3) Kopieren Sie alle Elemente in einem lokalen Cache (Collection
)
Iterate über alle Positionen einmal und sie in eine lokale Sammlung setzen, die Sie verwenden können eine beliebige Anzahl von Iteratoren zu erwerben:
// read everything into a local cache
Collection<String> cache = new ArrayList<>();
while (iterator.hasNext()) cache.add(iterator.next());
// now you can get as many iterators from cache as required:
Iterator<String> iter = cache.iterator();
// use iter
iter = cache.iterator(); // once more
// use iter
...
- Vorteil: Einfach, schnell, sobald alle Daten zu implementieren, ist im Cache.
- Nachteil: Zusätzlicher Speicher für Cache erforderlich.
(4) Datenquelle API ändern ihre Umsetzung zu lassen, das Problem
Bedeutung Griff: getQuestionIterator(File file)
Ändern eines Iterable<String>
anstelle eines Iterator<String>
zurückzukehren. Sie können eine beliebige Anzahl von Iteratoren von einem Iterable
gewinnen:
Iterable<String> iterable = getQuestionIterator(File file);
Iterator<String> iter = iterable.iterator();
// use iter
iter = iterable.iterator(); // once more
// use iter
- Vorteil: Die zugrunde liegende Datenquelle weiß am besten, wie Sie Ihre Daten zwischenzuspeichern. Sie müssen Ihre Daten nicht kopieren, wenn die zugrunde liegende Datenquelle bereits einen Cache verwendet.
- Nachteil: Es ist nicht immer möglich, die API zu ändern.
Der einfachste Weg besteht darin, jedes Mal einen neuen Iterator zu erstellen. Siehe http://stackoverflow.com/questions/7689261/why-iterator-doesnt-have-any-reset-method – NaN
Wenn dies bedeutet, dass 'getQuestionIterator()' ein teurer Aufruf ist (dh, es gibt Datei-I/O) , können Sie geladene Fragen in einige In-Memory-Sammlung speichern und durchlaufen sie über alle außer ersten Schleife der äußeren Schleife ('für (Person)') –
Wieder geöffnet, weil es scheint, der Iterator ist teuer, neu zu erstellen (die nicht gesetzt wurde in der Duplikatfrage). – Thilo