Como otros han dicho, un Iterable se puede llamar varias veces, devolviendo un nuevo iterador en cada llamada; un iterador se usa solo una vez. Entonces están relacionados, pero tienen diferentes propósitos. Sin embargo, frustrantemente, el método "compacto para" funciona solo con un iterable.
Lo que describiré a continuación es una forma de tener lo mejor de ambos mundos: devolver un Iterable (para una sintaxis más agradable) incluso cuando la secuencia de datos subyacente es única.
El truco consiste en devolver una implementación anónima de Iterable que realmente active el trabajo. Entonces, en lugar de hacer el trabajo que genera una secuencia única y luego devolver un iterador sobre eso, devuelve un Iterable que, cada vez que se accede, vuelve a hacer el trabajo. Puede parecer un desperdicio, pero a menudo solo llamarás al Iterable de todos modos, e incluso si lo llamas varias veces, todavía tiene una semántica razonable (a diferencia de un contenedor simple que hace que un Iterador "parezca" un Iterable, esto ganó ' t falla si se usa dos veces).
Por ejemplo, supongamos que tengo un DAO que proporciona una serie de objetos de una base de datos y quiero proporcionar acceso a eso a través de un iterador (por ejemplo, para evitar crear todos los objetos en la memoria si no son necesarios). Ahora podría devolver un iterador, pero eso hace que usar el valor devuelto en un bucle sea feo. Entonces, en cambio, envuelvo todo en un anon 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();
}
};
}
}
Esto se puede usar en un código como este:
class DaoUser {
private MetricDao dao;
for (Metric existing : dao.loadAll()) {
// do stuff here...
}
}
lo que me permite usar el bucle compacto para mantener el uso de memoria incremental.
Este enfoque es "vago": el trabajo no se realiza cuando se solicita el Iterable, sino solo más tarde cuando se repite el contenido, y debe ser consciente de las consecuencias de eso. En el ejemplo con un DAO que significa iterar sobre los resultados dentro de la transacción de la base de datos.
Así que hay varias advertencias, pero esto puede ser una expresión útil en muchos casos.