다른 사람들이 말했듯이, Iterable은 여러 번 호출 될 수 있으며 각 호출마다 새로운 Iterator를 반환합니다. 반복자는 한 번만 사용됩니다. 그래서 그들은 관련되어 있지만 다른 목적으로 사용됩니다. 그러나 "compact for"방법은 반복적으로 만 작동합니다.
아래에서 설명하는 것은 두 데이터를 모두 활용하는 한 가지 방법입니다. 기본 데이터 시퀀스가 일 회일 때도 (더 나은 구문을 위해) Iterable을 반환합니다.
트릭은 실제로 작업을 트리거하는 Iterable의 익명 구현을 리턴하는 것입니다. 따라서 일회성 시퀀스를 생성 한 다음 반복자를 반환하는 작업을 수행하는 대신 액세스 할 때마다 작업을 다시 실행하는 Iterable을 반환합니다. 그것은 낭비 적 인 것처럼 보일 수도 있지만, 어쨌든 한 번만 Iterable을 호출 할 것입니다. 여러 번 호출하더라도 여전히 합리적인 의미를 갖습니다 (Iterator를 "Iterable처럼 보이게하는 간단한 래퍼와 달리" 두 번 사용하면 실패합니다).
예를 들어, 데이터베이스에서 일련의 객체를 제공하는 DAO가 있고 반복자를 통해 액세스 할 수 있도록하려고합니다 (예 : 필요하지 않은 경우 메모리에 모든 객체를 생성하지 않기 위해). 이제 반복자를 반환 할 수는 있지만 반환 된 값을 루프에서 못 생겼습니다. 따라서 대신 모든 것을 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();
}
};
}
}
그러면 다음과 같은 코드에서 사용될 수 있습니다.
class DaoUser {
private MetricDao dao;
for (Metric existing : dao.loadAll()) {
// do stuff here...
}
}
그래도 증분 메모리 사용을 유지하면서 컴팩트 한 for 루프를 사용할 수 있습니다.
이 접근 방식은 "게으른"것입니다. Iterable이 요청 될 때 작업이 완료되지 않고 나중에 내용이 반복 될 때만 수행되며 그 결과를 알고 있어야합니다. DAO가있는 예에서 이는 데이터베이스 트랜잭션 내에서 결과를 반복한다는 의미입니다.
따라서 여러 가지 경고가 있지만 여전히 많은 경우에 유용한 관용구가 될 수 있습니다.