原生 getter 实现延迟初始化的核心是将迭代器创建推迟到首次调用时,避免未使用即加载;配合私有字段与 synchronized getter 可保障线程安全,适用于高成本创建场景;结合 supplier、optional 和 streamsupport.stream 可提升表达力与按需拉取能力;kotlin/scala 有更简洁的 lazy 语法支持。

直接用原生 getter 实现延迟初始化,核心是把迭代器的创建逻辑从字段声明或构造阶段,挪到 getter 第一次被调用时。这样只要没人调用这个 getter,迭代器就不会创建——连接不建立、数据不加载、对象不实例化。
用私有字段 + 同步 getter 封装迭代器
适合需要线程安全、且迭代器创建成本高(如依赖远程服务、大文件扫描、数据库游标)的场景:
- 声明一个私有字段,初始为 null
- getter 方法加 synchronized,检查字段是否为空;为空则创建并赋值,否则直接返回缓存值
- 避免双重检查锁(DCL)的复杂性,除非性能压测证明必须优化
示例:
private Iterator<record> heavyIterator;
public synchronized Iterator<record> getHeavyIterator() {
if (heavyIterator == null) {
heavyIterator = createExpensiveIterator(); // 如:new DatabaseCursorIterator(...)
}
return heavyIterator;
}
</record></record>
配合 Supplier 和 Optional 提升表达力
当迭代器创建逻辑本身可复用、或需与 Optional 流式链路集成时,用 Supplier 更清晰:
- 把创建逻辑封装进 Supplier,getter 内部用 orElseGet 模式控制触发时机
- 若迭代器可能为 null(比如条件未满足),可用 Optional
> 包一层,让调用方明确处理“无迭代器”分支
示例:
private final Supplier<iterator>> iteratorSupplier = () -> createExpensiveIterator();
private volatile Iterator<record> cachedIterator;
public Iterator<record> getHeavyIterator() {
if (cachedIterator == null) {
synchronized (this) {
if (cachedIterator == null) {
cachedIterator = iteratorSupplier.get();
}
}
}
return cachedIterator;
}
</record></record></iterator>
结合流式操作链做真正“按需拉取”
getter 延迟初始化只是第一步;要彻底避免冗余计算,还得让迭代过程本身不提前触发:
- 不要在 getter 里调用 iterator.forEachRemaining() 或转成 List —— 这会立即消费全部数据
- 确保下游使用的是 StreamSupport.stream(iterator, false),并保持 lazy 特性
- 过滤(filter)、映射(map)等操作尽量前置,让迭代器只生成真正需要的元素
例如:先 filter 再 map,而不是反过来。否则每条原始记录都得先解析再判断是否保留。
注意 Kotlin/Scala 等语言的原生支持
如果你用的是 Kotlin,直接用 by lazy 最简洁:
val heavyIterator: Iterator<record> by lazy {
createExpensiveIterator()
}
</record>
它默认线程安全、只执行一次、且不初始化直到首次访问。Scala 可用 lazy val 达到同样效果。Java 中没有完全等价语法,但同步 getter 是最贴近、最可控的替代方案。











