Như những người khác đã nói, một Iterable có thể được gọi nhiều lần, trả về một Iterator mới trên mỗi cuộc gọi; một Iterator được sử dụng chỉ một lần. Vì vậy, chúng có liên quan, nhưng phục vụ các mục đích khác nhau. Tuy nhiên, thật khó chịu, phương pháp "compact for" chỉ hoạt động với một lần lặp.
Những gì tôi sẽ mô tả dưới đây là một cách để có được cả hai thế giới tốt nhất - trả về một Iterable (cho cú pháp đẹp hơn) ngay cả khi chuỗi dữ liệu cơ bản là một lần.
Bí quyết là trả lại một triển khai ẩn danh của Iterable thực sự kích hoạt công việc. Vì vậy, thay vì thực hiện công việc tạo ra một chuỗi một lần và sau đó trả lại một Iterator qua đó, bạn trả lại một Iterable mà mỗi lần nó được truy cập sẽ làm lại công việc. Điều đó có vẻ lãng phí, nhưng thường thì bạn sẽ chỉ gọi Iterable một lần, và ngay cả khi bạn gọi nó nhiều lần, nó vẫn có ngữ nghĩa hợp lý (không giống như một trình bao bọc đơn giản làm cho Iterator "trông giống như" Iterable, điều này đã thắng ' t thất bại nếu sử dụng hai lần).
Ví dụ: giả sử tôi có một DAO cung cấp một loạt các đối tượng từ cơ sở dữ liệu và tôi muốn cung cấp quyền truy cập thông qua một trình vòng lặp (ví dụ: để tránh tạo tất cả các đối tượng trong bộ nhớ nếu không cần thiết). Bây giờ tôi chỉ có thể trả về một trình vòng lặp, nhưng điều đó làm cho việc sử dụng giá trị được trả về trong một vòng lặp trở nên xấu xí. Vì vậy, thay vào đó tôi bọc mọi thứ trong một vòng lặp lặp lại:
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();
}
};
}
}
điều này sau đó có thể được sử dụng trong mã như thế này:
class DaoUser {
private MetricDao dao;
for (Metric existing : dao.loadAll()) {
// do stuff here...
}
}
cho phép tôi sử dụng vòng lặp compact cho vòng lặp mà vẫn giữ mức sử dụng bộ nhớ tăng dần.
Cách tiếp cận này là "lười biếng" - công việc không được thực hiện khi Iterable được yêu cầu, mà chỉ sau đó khi nội dung được lặp lại - và bạn cần nhận thức được hậu quả của điều đó. Trong ví dụ với DAO có nghĩa là lặp lại các kết quả trong giao dịch cơ sở dữ liệu.
Vì vậy, có nhiều cảnh báo khác nhau, nhưng đây vẫn có thể là một thành ngữ hữu ích trong nhiều trường hợp.