subList 提供轻量级子集视图,不复制元素但与原列表强绑定;仅适用于只读分页,需校验索引边界,必要时转为不可变视图或新 ArrayList 副本,高并发读多写少场景可选 CopyOnWriteArrayList。

用 subList 实现轻量级子集视图
Java 的 List.subList(int fromIndex, int toIndex) 是最直接的分页视图手段,它不复制元素,只返回原列表的逻辑视图,内存开销极小。但要注意:该视图与原列表强绑定,任何对子视图的结构性修改(如 add、remove)都会抛 UnsupportedOperationException(除非底层是 ArrayList 且未被不可变包装),而对原列表的修改可能使子视图失效或引发 ConcurrentModificationException。
安全用法建议:
- 仅用于只读分页展示,避免调用 add/remove/clear 等结构变更方法
- 分页前先校验索引边界:Math.max(0, from) 和 Math.min(list.size(), to),防止 IndexOutOfBoundsException
- 若需独立副本,显式构造新 ArrayList:new ArrayList(list.subList(from, to))
手动计算分页范围并提取子集
对任意 List(包括不可变或线程不安全实现),最稳妥的分页方式是手动截取索引范围并创建新列表。这种方式完全解耦,适合多线程环境或需要稳定快照的场景。
通用分页工具方法示例:
立即学习“Java免费学习笔记(深入)”;
- 计算起始索引:int from = Math.min(list.size(), page * pageSize)
- 计算结束索引:int to = Math.min(list.size(), from + pageSize)
- 安全提取:list.subList(from, to).toArray() 或封装为新 ArrayList
- 返回空列表而非 null,避免空指针风险
结合 Collections.unmodifiableList 提升只读安全性
当分页结果仅用于下游消费(如 API 响应、前端渲染),可将 subList 包装为不可变视图,从 API 层面杜绝误修改。
- 写法:Collections.unmodifiableList(list.subList(from, to))
- 优势:即使传入的是可变列表,下游也无法调用 add/remove,且异常信息明确
- 注意:仍需确保原列表在视图生命周期内不被并发修改,否则迭代时仍可能报 ConcurrentModificationException
高并发场景下推荐使用 CopyOnWriteArrayList + 分页快照
若列表本身高频读、低频写,且分页操作需绝对线程安全,CopyOnWriteArrayList 是更优选择。它的 subList 返回的视图基于当前快照,不受后续写操作影响。
- 适用场景:配置项列表、通知模板池、监控指标元数据等读多写少集合
- 代价:写操作复制整个数组,不适合大列表或频繁更新
- 分页时无需额外同步,直接 subList 即可获得一致性视图


















