Как уже говорили другие, Iterable может вызываться несколько раз, возвращая новый Iterator при каждом вызове; Итератор используется только один раз. Таким образом, они связаны, но служат различным целям. Однако, к сожалению, метод «компактный для» работает только с итерацией.
Ниже я опишу один из способов получить лучшее из обоих миров - вернуть Iterable (для лучшего синтаксиса), даже если базовая последовательность данных одноразовая.
Хитрость заключается в том, чтобы вернуть анонимную реализацию Iterable, которая фактически запускает работу. Таким образом, вместо того, чтобы выполнять работу, которая генерирует одноразовую последовательность, а затем возвращать Итератор, вы возвращаете Итерируемый, который при каждом обращении к нему повторяет работу. Это может показаться расточительным, но часто вы все равно будете вызывать Iterable только один раз, и даже если вы вызываете его несколько раз, он все еще имеет разумную семантику (в отличие от простой оболочки, которая делает Iterator «похожим» на Iterable, это выиграет » не удается, если используется дважды).
Например, скажем, у меня есть DAO, который предоставляет серию объектов из базы данных, и я хочу предоставить доступ к нему через итератор (например, чтобы избежать создания всех объектов в памяти, если они не нужны). Теперь я могу просто вернуть итератор, но это делает использование возвращаемого значения в цикле уродливым. Поэтому вместо этого я обертываю все в один итеративный:
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();
}
};
}
}
это может тогда использоваться в коде как это:
class DaoUser {
private MetricDao dao;
for (Metric existing : dao.loadAll()) {
// do stuff here...
}
}
который позволяет мне использовать компактный цикл for, сохраняя при этом добавочное использование памяти.
Этот подход является «ленивым» - работа не выполняется, когда запрашивается Iterable, а только позже, когда содержимое повторяется, - и вам нужно знать о последствиях этого. В примере с DAO это означает итерацию результатов в транзакции базы данных.
Таким образом, существуют различные предостережения, но во многих случаях это может быть полезной идиомой.