Jak powiedzieli inni, Iterable można wywołać wiele razy, zwracając nowy Iterator przy każdym wywołaniu; iterator jest używany tylko raz. Są więc powiązane, ale służą innym celom. Frustrujące jest jednak to, że metoda „compact for” działa tylko z iteracją.
To, co opiszę poniżej, to jeden ze sposobów na uzyskanie najlepszego z obu światów - zwracanie Iterable (dla lepszej składni), nawet gdy leżąca u podstaw sekwencja danych jest jednorazowa.
Sztuka polega na zwróceniu anonimowej implementacji Iterable, która faktycznie uruchamia pracę. Zamiast więc wykonać pracę, która generuje jednorazową sekwencję, a następnie zwrócić iterator, zwraca Iterable, który za każdym razem, gdy jest uzyskiwany dostęp, przerywa pracę. Może się to wydawać marnotrawstwem, ale często i tak wywołujesz Iterable tylko raz, a nawet jeśli wywołasz to wiele razy, nadal ma rozsądną semantykę (w przeciwieństwie do prostego opakowania, które sprawia, że Iterator „wygląda jak” Iterowalny, to wygrało ” nie powiedzie się, jeśli zostanie użyty dwukrotnie).
Powiedzmy na przykład, że mam DAO, która udostępnia serię obiektów z bazy danych, i chcę zapewnić do nich dostęp za pośrednictwem iteratora (np. Aby uniknąć tworzenia wszystkich obiektów w pamięci, jeśli nie są one potrzebne). Teraz mógłbym po prostu zwrócić iterator, ale to sprawia, że używanie zwracanej wartości w pętli jest brzydkie. Zamiast tego zawijam wszystko w 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();
}
};
}
}
można to następnie wykorzystać w kodzie:
class DaoUser {
private MetricDao dao;
for (Metric existing : dao.loadAll()) {
// do stuff here...
}
}
co pozwala mi korzystać z kompaktowej pętli dla, jednocześnie zachowując przyrostowe użycie pamięci.
To podejście jest „leniwe” - praca nie jest wykonywana na żądanie Iterable, ale dopiero później, gdy zawartość jest iterowana - i musisz zdawać sobie sprawę z konsekwencji tego. W przykładzie z DAO oznacza to iterację wyników w ramach transakcji bazy danych.
Istnieją więc różne zastrzeżenia, ale w wielu przypadkach może to nadal być przydatnym idiomem.