Java中Iterator分批读取的核心是用其配合外部循环与计数器实现按块遍历,而非Iterator自身支持分页;通过while+for累积固定数量元素到临时列表,处理后清空,避免全量加载内存。

Java 中 Iterator 处理大型集合分批读取,关键不是让 Iterator 本身“分批”,而是用它配合外部控制逻辑实现按块遍历。Iterator 本身是单次、顺序、不可重置的游标,不支持跳转或分页;但你可以用它作为底层遍历工具,在每次循环中累积固定数量元素,达到“分批”效果。
分批读取的核心思路
把 Iterator 当作数据拉取管道,用 while 循环 + 计数器或集合容器控制每轮处理多少个元素,避免一次性加载全量到内存。
- 每次调用
hasNext()和next()获取一个元素 - 用
List<T>或其他临时容器暂存一批(如 1000 个) - 达到批次大小后,处理这批数据(入库、计算、发送等),再清空容器继续
- 不依赖
size()或get(i)—— 这对 LinkedList、Stream 或自定义惰性集合可能不可用或低效
示例:将大 List
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
List<Integer> hugeList = ...; // 可能含百万级元素
Iterator<Integer> iter = hugeList.iterator();
int batchSize = 500;
while (iter.hasNext()) {
List<Integer> batch = new ArrayList<>(batchSize);
for (int i = 0; i < batchSize && iter.hasNext(); i++) {
batch.add(iter.next());
}
processBatch(batch); // 自定义处理逻辑,如批量插入数据库
}避免常见陷阱
-
不要在遍历中修改原集合结构:比如
list.remove()会触发ConcurrentModificationException,除非用iterator.remove()且仅删刚取的元素 -
不要试图用
skip(n).limit(m)包装普通 Iterator:那是 Stream 的语义,Iterator 无 skip 能力;若需随机分页(如取第 3 页),应改用索引访问(List.get(i))或预建偏移索引(适用于文件/数据库场景) - 别缓存全部元素再切片:违背“分批”初衷,失去内存优势
对接真实大数据场景的延伸方式
当集合源头本身就是流式或不可随机访问时(如大文件行迭代、数据库游标、网络响应流),推荐封装成 Iterator<T> 子类,内部持 BufferedReader 或 ResultSet,让 next() 触发一次 I/O,天然支持分批:
立即学习“Java免费学习笔记(深入)”;
- 文本文件:用
BufferedReader封装为Iterator<String>,每批读 N 行 - 数据库结果集:用
ResultSet封装为Iterator<Row>,next()调用rs.next(),配合setFetchSize(n)提升 JDBC 批获取效率 - 自定义惰性集合:重写
hasNext()/next(),按需生成或加载下一批数据
本质上,Iterator 是“拉模式”的基础载体,分批是上层控制策略。只要保持每次只拉少量、处理完即丢弃,就能稳住内存水位。

















