Come altri hanno già detto, un Iterable può essere chiamato più volte, restituendo un nuovo Iterator ad ogni chiamata; un Iteratore viene usato solo una volta. Quindi sono correlati, ma servono a scopi diversi. Frustrante, tuttavia, il metodo "compatto per" funziona solo con un iterabile.
Quello che descriverò di seguito è un modo per avere il meglio di entrambi i mondi: restituire un Iterable (per una sintassi migliore) anche quando la sequenza di dati sottostante è una tantum.
Il trucco è restituire un'implementazione anonima di Iterable che in realtà avvia il lavoro. Quindi, invece di eseguire il lavoro che genera una sequenza una tantum e quindi restituire un Iteratore su quello, si restituisce un Iterable che, ogni volta che si accede, ripete il lavoro. Ciò potrebbe sembrare dispendioso, ma spesso chiamerai l'Iterable solo una volta comunque, e anche se lo chiami più volte, ha ancora una semantica ragionevole (a differenza di un semplice wrapper che rende un Iterator "simile" a Iterable, questo ha vinto ' non fallire se usato due volte).
Ad esempio, supponiamo di avere un DAO che fornisce una serie di oggetti da un database e che voglio fornire accesso a tale tramite un iteratore (ad es. Per evitare di creare tutti gli oggetti in memoria se non sono necessari). Ora potrei semplicemente restituire un iteratore, ma ciò rende brutto l'utilizzo del valore restituito in un ciclo. Quindi invece avvolgo tutto in un altro Iterable:
class MetricDao {
...
/**
* @return All known metrics.
*/
public final Iterable<Metric> loadAll() {
return new Iterable<Metric>() {
@Override
public Iterator<Metric> iterator() {
return sessionFactory.getCurrentSession()
.createQuery("from Metric as metric")
.iterate();
}
};
}
}
questo può quindi essere utilizzato in codice come questo:
class DaoUser {
private MetricDao dao;
for (Metric existing : dao.loadAll()) {
// do stuff here...
}
}
che mi permette di usare il compatto per loop pur mantenendo un uso incrementale della memoria.
Questo approccio è "pigro" - il lavoro non viene svolto quando viene richiesto l'Iterable, ma solo successivamente quando i contenuti vengono ripetuti - e devi essere consapevole delle conseguenze di ciò. Nell'esempio con un DAO che significa scorrere i risultati all'interno della transazione del database.
Quindi ci sono vari avvertimenti, ma questo può essere ancora un utile linguaggio in molti casi.