应使用 while 循环控制分页边界,内部用 for-each 遍历 subList 视图;subList 是左闭右开区间,需用 Math.min 防越界,且注意其视图特性带来的并发与修改风险。

在 Java 中,用 for-each 配合 List.subList() 实现分页处理大数据集,**看似简洁,但需特别注意 subList 返回的是原列表的视图,且 for-each 无法直接控制起止索引——必须配合循环逻辑手动切片**。直接写成 for (Item item : list.subList(from, to)) 只能处理一页,要“按页分批”,得在外层用传统 for 或 while 控制页边界。
明确分页逻辑:计算每页起止索引
subList(fromIndex, toIndex) 是左闭右开区间(包含 fromIndex,不包含 toIndex),因此一页大小为 pageSize 时:
- 第
i页(从 0 开始)的起始索引是i * pageSize - 结束索引是
Math.min((i + 1) * pageSize, list.size()),防止越界 - 当起始索引 ≥ 列表大小时,循环应终止
用 while 循环驱动分页,内部用 for-each 处理当前页
这是最清晰、不易出错的方式。避免在 for-each 中嵌套索引计算,把分页控制权交给外层循环:
int pageSize = 100;
int start = 0;
List<string> data = getData(); // 假设这是你的大数据列表
<p>while (start page = data.subList(start, end);</p>
<pre class="brush:php;toolbar:false;">// ✅ 安全使用 for-each 遍历当前页
for (String item : page) {
process(item); // 你的业务处理逻辑
}
start = end; // 移动到下一页
}
注意 subList 的“视图”特性与并发/修改风险
subList 不创建新列表,只是原列表的动态视图。这意味着:
- 如果原列表在分页过程中被其他线程修改(如 add/remove),
subList操作可能抛ConcurrentModificationException - 对
subList的修改(如set())会直接影响原列表;但调用clear()或add()会改变结构,导致后续subList失效 - 若需完全隔离(例如多线程并行处理各页),应显式复制:
new ArrayList(data.subList(start, end))
替代方案:用 Stream.iterate 或自定义分页迭代器(Java 9+)
若追求更函数式或复用性,可封装为迭代器:
public static <t> Stream<list>> partition(List<t> list, int size) {
return IntStream.iterate(0, i -> i i + size)
.mapToObj(i -> list.subList(i, Math.min(i + size, list.size())));
}
<p>// 使用
partition(data, 100).forEach(page -> {
for (String item : page) {
process(item);
}
});</p></t></list></t>
这种方式将分页逻辑抽象出来,for-each 仍用于每页内部,语义更清晰,也便于测试和复用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











