当前位置: 首页 > news >正文

list分页

处理几万条数据的 List 分页,关键在于平衡​​性能​​、​​内存占用​​和​​开发效率​​。下面我用一个表格为你总结几种主流方法的优缺点,帮你快速决策:

方法

优点

缺点

适用场景

subList()

​性能极佳​​ (返回原列表视图,不创建新集合)

分页结果与原列表​​绑定​​,原列表修改会影响分页结果

需要​​最高性能​​、且能接受分页结果与源数据联动的大数据量分页

​Stream API​

​函数式风格​​,代码简洁,可与流操作链式组合

会​​创建新列表​​,有一定内存开销

适合在分页​​前后需要进行复杂数据操作​​(如过滤、映射)的场景

​Apache Commons​

代码简洁,一次分块可多次取页,​​生成真实副本​​,数据隔离性好

需引入 commons-collections4依赖

需要​​数据隔离​​或已使用该库的其他功能时

​Google Guava​

与 Apache Commons 类似,提供​​更丰富的集合操作​​功能

需引入 guava依赖

项目已使用 Guava 或需要其更多集合工具时


🛠️ 代码示例与说明

1. 使用 subList()(性能最佳)
public static <T> List<T> paginateBySubList(List<T> sourceList, int pageNum, int pageSize) {if (sourceList == null || sourceList.isEmpty()) {return Collections.emptyList();}int totalItems = sourceList.size();int fromIndex = (pageNum - 1) * pageSize;if (fromIndex >= totalItems) {return Collections.emptyList(); // 请求页码超出范围,返回空列表}int toIndex = Math.min(fromIndex + pageSize, totalItems);return sourceList.subList(fromIndex, toIndex);
}

​关键说明​​:subList()返回的是原列表的一个​​视图​​。这意味着:

  • ​优点​​:性能极高,因为不会复制数据,只是包装了一个偏移量。

  • ​注意​​:如果你不希望分页的结果随着原列表的修改而改变,或者原列表可能被修改导致分页结果失效,你需要创建它的副本:return new ArrayList<>(sourceList.subList(fromIndex, toIndex));

2. 使用 Stream API(函数式风格)
public static <T> List<T> paginateByStream(List<T> sourceList, int pageNum, int pageSize) {if (sourceList == null || sourceList.isEmpty()) {return Collections.emptyList();}return sourceList.stream().skip((pageNum - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
}

​关键说明​​:这种方式会​​创建新的列表对象​​,因此内存开销比 subList()大,但代码非常清晰,尤其适合在分页前后进行过滤、映射等流操作。

3. 使用 Apache Commons Collections
// 首先需要引入依赖:org.apache.commons:commons-collections4
import org.apache.commons.collections4.ListUtils;public static <T> List<T> paginateByApacheCommons(List<T> sourceList, int pageNum, int pageSize) {if (sourceList == null || sourceList.isEmpty()) {return Collections.emptyList();}List<List<T>> partitions = ListUtils.partition(sourceList, pageSize); // 先按页大小分割if (pageNum < 1 || pageNum > partitions.size()) {return Collections.emptyList();}return partitions.get(pageNum - 1);
}

​关键说明​​: ListUtils.partition会先将列表按指定大小分块,返回一个包含各分块视图的列表。获取某一页时,get方法会​​创建该分块的新列表副本​​,因此返回的数据与原列表隔离,不受修改影响。

4. 使用 Google Guava
// 首先需要引入依赖:com.google.guava:guava
import com.google.common.collect.Lists;public static <T> List<T> paginateByGuava(List<T> sourceList, int pageNum, int pageSize) {if (sourceList == null || sourceList.isEmpty()) {return Collections.emptyList();}List<List<T>> partitions = Lists.partition(sourceList, pageSize);if (pageNum < 1 || pageNum > partitions.size()) {return Collections.emptyList();}return partitions.get(pageNum - 1);
}

​关键说明​​: 其原理和用法与 Apache Commons 非常相似,同样会生成数据隔离的分页结果。如果你的项目已经大量使用 Guava,这是不错的选择。


⚠️ 重要提醒与优化建议

处理几万条数据时,以下几点至关重要:

  1. ​数据来源是根本​​:如果这些数据来自​​数据库​​,​​强烈建议直接在数据库查询时进行分页​​(如 SQL 的 LIMIT ... OFFSETROW_NUMBER()或 MyBatis PageHelper 等),而不是将所有数据读到内存中再分页。这是处理大数据集最有效的方法。

  2. ​内存警告​​:将几万条数据全部加载到内存中本身就有​​内存溢出(OOM)的风险​​。请务必评估你的列表大小和JVM内存设置。

  3. ​边界处理​​:所有示例中都包含了对空列表、页码越界的检查,这是生产代码中必不可少的。

  4. ​页码惯例​​:通常​​页码 (pageNum) 从 1 开始​​计算。

  5. ​考虑更优分页策略​​:对于超大数据集,传统的 LIMIT ... OFFSET在深度分页时性能会下降。可以考虑基于​​游标(Cursor)​​ 或​​上次检索到的最大ID​​的分页方式(例如 WHERE id > ? ORDER BY id LIMIT ?),性能更稳定。


💡 如何选择?

  • ​追求极致性能​​,且能接受分页视图与原列表的关联:选 ​subList()​。

  • 需要在分页流程中集成​​复杂的流式操作​​:选 ​​Stream API​​。

  • ​希望代码简洁​​,且需要​​分页结果与原列表数据隔离​​:选择 ​​Apache Commons​​ 或 ​​Google Guava​​。两者类似,取决于你的项目依赖偏好。

  • ​最重要的一点​​:如果数据源自数据库,​​务必在SQL查询层面进行分页​​,这是最根本的优化。

希望这些信息能帮助你为几万条数据选择合适的分页方法!


文章转载自:

http://iNfTm6qx.qfzjn.cn
http://8zPV63uc.qfzjn.cn
http://RZkLk3mK.qfzjn.cn
http://EL8puQhp.qfzjn.cn
http://uavmAnLE.qfzjn.cn
http://HCgqUCWA.qfzjn.cn
http://8c5MWoUa.qfzjn.cn
http://MFGfjPys.qfzjn.cn
http://dsFyHnpd.qfzjn.cn
http://gTVpSGrs.qfzjn.cn
http://lnLjZjRj.qfzjn.cn
http://BXjlSmgX.qfzjn.cn
http://jTy7fJ77.qfzjn.cn
http://Gxkfp4E8.qfzjn.cn
http://CT4PkKz1.qfzjn.cn
http://M4xrdEyo.qfzjn.cn
http://r3m9S4p5.qfzjn.cn
http://tu0ejX28.qfzjn.cn
http://D5ydOFfR.qfzjn.cn
http://Nk80EEEU.qfzjn.cn
http://ck9ZtIAn.qfzjn.cn
http://6TgtJZa9.qfzjn.cn
http://R4SYv47E.qfzjn.cn
http://puFjY1qC.qfzjn.cn
http://K5as0k8C.qfzjn.cn
http://xi50Xy5Z.qfzjn.cn
http://RyW368DE.qfzjn.cn
http://0DaIfMYV.qfzjn.cn
http://D9gAhPiz.qfzjn.cn
http://A84SSPoE.qfzjn.cn
http://www.dtcms.com/a/378953.html

相关文章:

  • 寻求多维表格有哪些服务商?Teable、飞书、WPS、简道云和Airtable
  • 6-获取磁盘分区信息
  • GRASP 实验室研究 论文解读 | 机器人交互:基于神经网络引导变分推理的快速失配估计
  • 元宇宙与金融创新:虚实融合下的金融服务新形态
  • 【基于协同过滤的校园二手交易平台】
  • Oracle APEX 定型文(快速选取功能)
  • 小说创作中的时间轴体验设计:事序图交互与用户体验优化
  • Liunx执行source /etc/profile 报错, -bash: HISTTIMEFORMAT: readonly variable
  • js的事件循环机制的理解
  • MATLAB基于博弈论-云模型的城市道路塌陷风险评价模型
  • 医保购药平台如何对接互联网医院系统源码?技术难点与解决方案
  • 景观设计师的数字画笔:园林景观设计软件有哪些
  • 配置docker常见问题
  • 华宇TAS应用中间件与瀚高股份两款产品完成兼容互认证
  • 详解 C++11
  • GS1-128 校验码计算方法
  • UnityShader:正反面显示不同颜色
  • c++打包pyd文件给Python使用调用函数
  • 设计模式-适配器备忘录组合迭代器
  • Linux上解决telnet失败问题
  • xtuner安装及微调大模型
  • FlexSPI 传输结构体解析
  • 简单的GIT操作学习记录
  • K8S的dashboard部署与访问
  • css之一个元素可以同时应用多个动画效果
  • STM32之水质浑浊度传感器模块
  • 【Qt】【C++】虚析构函数及 virtual ~Base() = default
  • 马斯克访谈深度解读:机器人、AI芯片与人类文明的未来
  • 深入理解 CMake 脚本片段:文件查找、字符串替换与条件处理
  • Google Ads广告验证全攻略:如何借助动态住宅IP精准投放?