Java中Iterator本身不支持分页,但可通过封装PageIterator类实现分页语义:按页加载数据、懒加载、缓存当前页,对外仍提供标准hasNext()/next()接口。

Java 中不能直接用 Iterator 实现“分页”功能,因为标准 Iterator 是单向、一次性、无状态偏移的——它不支持跳过前 N 条或重置位置。但你可以封装一个 支持分页语义的迭代器包装类,按页大小(page size)批量拉取数据,并在每页内提供标准 Iterator 接口。
核心思路:用“懒加载 + 页缓存”模拟分页迭代
不是让一个 Iterator 跳到第 500 页,而是:
- 每次调用 next() 时,内部确保当前页已加载;
- 当前页遍历完,自动加载下一页(从数据源/列表/数据库等);
- 外部仍用 hasNext()/next(),行为像普通迭代器,但底层是分页驱动的。
实现一个 PageIterator(基于 List 的简单示例)
假设你有一大个 List<t></t>,不想一次性全加载进内存,而是按页读取:
public class PageIterator<T> implements Iterator<T> {
private final List<T> source;
private final int pageSize;
private int currentPage = 0;
private int currentIndexInPage = 0;
private List<T> currentPageData = Collections.emptyList();
<pre class='brush:java;toolbar:false;'>public PageIterator(List<T> source, int pageSize) {
this.source = Objects.requireNonNull(source);
this.pageSize = Math.max(1, pageSize);
}
@Override
public boolean hasNext() {
// 如果当前页还有元素,返回 true
if (currentIndexInPage < currentPageData.size()) {
return true;
}
// 否则尝试加载下一页
int start = currentPage * pageSize;
if (start >= source.size()) {
return false;
}
int end = Math.min(start + pageSize, source.size());
currentPageData = source.subList(start, end);
currentIndexInPage = 0;
currentPage++;
return !currentPageData.isEmpty();
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return currentPageData.get(currentIndexInPage++);
}}
更实用的场景:对接数据库或流式数据源
真实分页常来自 JDBC、MyBatis 或 REST API。这时应把“加载下一页”的逻辑抽成抽象方法,由子类实现:
立即学习“Java免费学习笔记(深入)”;
- 定义
protected abstract List<t> fetchPage(int pageNum, int pageSize)</t> - 在
hasNext()中按需调用,缓存结果 - 避免预加载全部页,只保当前页 + 下一页准备位(可选)
- 注意线程安全:
PageIterator默认非线程安全,多线程请加同步或用ThreadLocal
使用示例
假设有 1000 条用户数据,每次只取 20 条:
List<User> allUsers = loadAllUsersFromDB(); // 或换成分页加载代理
PageIterator<User> iter = new PageIterator<>(allUsers, 20);
<p>while (iter.hasNext()) {
User u = iter.next();
process(u); // 每次处理一条,但底层按页拉取
}</p>这种设计既保持了 Iterator 的简洁接口,又实现了内存友好的分页遍历。关键不在“改造 Iterator”,而在“用 Iterator 封装分页逻辑”。


















