Java中Iterator本身不直接实现惰性加载,但可通过自定义实现类在next()中按需获取数据,如文件逐行读取、数据库分页查询等,避免一次性加载全部数据。

Java 中的 Iterator 本身**不直接实现惰性加载**,它只是一个遍历接口;但你可以通过**自定义 Iterator 实现类**,在 next() 方法中按需拉取或生成数据,从而达成惰性加载效果。
惰性加载的核心思路
不是一次性把所有数据装进内存(比如 List),而是在每次调用 next() 时才获取下一项——可能是从数据库分页查、从文件读一行、从网络流取一个对象、或实时计算生成。
- 避免提前加载全部数据:尤其适合大数据集、IO 密集型或资源受限场景
- next() 是触发点:真正的数据获取逻辑写在这里,而不是构造时
- hasNext() 要轻量且可预测:不能有副作用,最好只做“是否还有下一项”的判断(如检查缓存、预读一个元素、查数据库是否有下一页)
一个简单示例:惰性读取大文件每行
假设你有一个超大文本文件,不想一次性读入内存:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
public class LineIterator implements Iterator<String> {
private final BufferedReader reader;
private String nextLine;
public LineIterator(String filePath) throws IOException {
this.reader = new BufferedReader(new FileReader(filePath));
this.nextLine = reader.readLine(); // 预读第一行,用于 hasNext 判断
}
@Override
public boolean hasNext() {
return nextLine != null;
}
@Override
public String next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
String line = nextLine;
try {
nextLine = reader.readLine(); // 真正的“加载下一项”发生在此
} catch (IOException e) {
throw new RuntimeException(e);
}
return line;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
// 别忘了关闭资源
public void close() throws IOException {
reader.close();
}
}
使用时:
立即学习“Java免费学习笔记(深入)”;
try (LineIterator it = new LineIterator("huge.log")) {
while (it.hasNext()) {
String line = it.next(); // 每次调用才读一行
process(line);
}
}
更通用的做法:配合 Supplier 或 Stream
Java 8+ 可借助 Stream.generate() 或自定义 Spliterator 实现更灵活的惰性源。例如:
- 用
Stream.iterate(0, i -> i + 1).limit(1000000)生成百万个数,但不会真创建百万对象,只在终端操作(如forEach)中逐个计算 - 封装数据库分页查询为 Iterator:
hasNext()查下一页是否存在,next()执行一次分页查询并返回首条记录 - 结合 CompletableFuture 或 Reactive Streams(如 Project Reactor 的
Flux)可实现异步惰性流,但已超出传统 Iterator 范畴
注意事项
- 线程不安全:标准 Iterator 不是线程安全的,多线程遍历时需同步或改用并发集合的迭代方式
-
资源管理要小心:像文件、数据库连接等必须显式关闭(推荐 try-with-resources,或提供
close()方法) -
fail-fast 行为可选:如果底层数据源被并发修改,可选择抛
ConcurrentModificationException(参考ArrayList.Itr),但惰性源往往无“底层数组”,所以通常不实现

















