当前位置:网站首页>分批数据遍历的优化
分批数据遍历的优化
2022-07-29 17:23:00 【逆水行舟没有退路】
文章目录
前言
有时候,我们进行大数据批量遍历检查等操作,常规的操作,我们通常需要手动实现分页形式的遍历,例如需要从数据库读取100万条记录,通常我们可能需要手动分批5000条一次进行数据读取和操作。
如何简化代码的书写,进行大数据的批量遍历。
传统的大批量的数据遍历的写法(仅作示例)
/** * 1. 计算总页数 */
String sql="select count(1) ct from xxxx";
//通过数据库,计算总页数
int pageSize=10;
/** * 2. 按页执行遍历 */
for(int i=0;i<pageSize;i++){
/** * 3. 单页查询遍历 */
String sql2="select * from xxxx limit "+(i*5000)+","+(i+1)*5000;
List list=new ArrayList<>(); //执行sql2获取数据
for(Object obj:list){
System.out.println(obj);
}
}
上面的代码大致是我们遍历数据库的操作,逻辑清晰,但是代码比较繁琐和冗长。
如何简化这种逻辑结构,实现更清晰简单的数据遍历。
我们通过自定义的遍历器,实现数据的遍历,简化遍历层级,实现一级遍历,不关注数据的分页拆分。
如何实现批量数据遍历
- 定义抽象的集合遍历器
package com.lengcz.tools;
import java.util.List;
/** * 数据遍历器 * * @author leng * @param <T> * */
public abstract class AbstractListIterator<T> {
private List<T> data;
private long index = -1;
/** * 分页数量 */
private int pageSize = 5000;
private int currentIndex = -1;
private long totalSize = 0;
private long pageNo = 0;
public AbstractListIterator() {
}
public AbstractListIterator(int pageSize) {
if (pageSize < 1) {
throw new IllegalArgumentException("pageSize must be greater than 0.");
}
this.pageSize = pageSize;
}
/** * 取得元素 * * @return */
public T get() {
return data.get(currentIndex);
}
/** * 去到下一个元素 * * @return */
public boolean toNext() {
boolean flag = true; // 角标是否+1
try {
if ((index + 1) >= totalSize) {
// 总数为0或者totalSize&pageSize等于0,则继续下一页的数据
if (totalSize == 0 || ((totalSize % pageSize) == 0)) {
// 数量为0或者总数整除pageSize,则翻下一页
List<T> tempData = getPage(totalSize, totalSize + pageSize);
if (null == tempData || tempData.size() == 0) {
flag = false;
return false;
}
pageNo++;
this.data = tempData;
totalSize = totalSize + tempData.size();
currentIndex = -1;
// System.out.println(data);
} else if (totalSize == (index + 1)) {
// 表示最后一个了
flag = false;
return false;
}
}
} finally {
if (flag) {
// 表示下标能移动
currentIndex++;// 当前下标
index++;// 总下标
}
}
return flag;
}
/** * 分页获取 * * @param fromIndex * 包含 * @param toIndex * 不包含 * @return */
public abstract List<T> getPage(long fromIndex, long toIndex);
/** * 测试输出 */
public void print() {
System.out.println("===========AbstractListIterator arguments==============");// 总指针下标
System.out.println("index:" + index);// 总指针下标
System.out.println("pageSize:" + pageSize);// 单页数
System.out.println("pageNo:" + pageNo);// 第x页
System.out.println("currentPageSize:" + (null != data ? data.size() : 0));// 当前页数据量
System.out.println("currentIndex:" + currentIndex);// 当前集合的真实下标
System.out.println("totalSize:" + totalSize);// 总数
System.out.println("data:" + data); // 数据集合
}
}
- 测试或者使用抽象遍历器,根据AbstractListIterator,我们只需要集成该类,实现getPage方法即可使用该类进行遍历,而不需要关心数据遍历
package com.lengcz.tools;
import java.util.ArrayList;
import java.util.List;
public class AbstractListIteratorTest {
/** * 构造的需要遍历的数据a0到a23 */
public static List<String> list=new ArrayList<>();
static{
for(int i=0;i<24;i++){
list.add("a"+i);
}
}
public static void main(String[] args) {
AbstractListIterator<String> it=new AbstractListIterator<String>(10) {
@Override
public List<String> getPage(long fromIndex, long toIndex) {
if(fromIndex>list.size()){
fromIndex=list.size();
}
if(toIndex>list.size()){
toIndex=list.size();
}
return list.subList((int)fromIndex,(int) toIndex);
}
};
System.out.println("=====进行数据遍历=====");
while(it.toNext()){
System.out.println(it.get());
}
it.print();//调试打印参数内容
}
}
注意: 这里pageSize为10是方便测试,建议设置为单词批量的处理值,例如5000
打印日志输出,只是通过简单的whie循环,即可实现全数据的遍历。
总结
实现分批数据遍历的方法分两步
(1) 继承AbstractListIterator类,实现getPage方法
(2) 使用where循环遍历
while(it.toNext()){
//切换到下一条
System.out.println(it.get()); //获取数据
}
边栏推荐
- [网络]WAN技术组播
- Pagination with LIMIT
- 常见的磁盘格式以及它们之间的区别
- 【考研英语词汇训练营】Day 16 —— bankrupt,remain,regulate,construct,reflect
- Six basic experiments of STC8h1k28
- UNIX Environment Advanced Programming Chapter 3
- 免费创建一个令人惊叹的网站的7个技巧
- [High Concurrency] I used multithreading to further optimize the massive data proofreading system under the billion-level traffic e-commerce business, and the performance has been improved by 200% aga
- 本周投融报:CeFi积聚风投吸引力
- 传统渲染农场和云渲染农场选择哪个好?
猜你喜欢
"Record" MMDetection Introduction
UNIX Environment Advanced Programming Chapter 3
学会 arthas,让你 3 年经验掌握 5 年功力!
leetcode136 -- 只出现一次的数字
In the Chinese ToB market, it is too difficult to choose the right supplier
mysql存储过程 实现全量同步数据并自动创建表
js选择多张图片对比功能插件
One's deceased father grind English vocabulary training camp Day 17 】 -- espresso, ultimate, gradually, detect, dimension
reading order
“大龄”裸辞的“孤勇者”们
随机推荐
Xatlas source code parsing (7)
详解析构函数、拷贝构造函数
“我“眼中的测试/开发程序员,预想与现实的碰撞......
lua-调试技巧
泰山OFFICE技术讲座:影响文字效果的因素,由四大升级为五大
mysql存储过程 实现全量同步数据并自动创建表
多线程顺序运行的 4 种方法,面试随便问!
学会 arthas,让你 3 年经验掌握 5 年功力!
【深度学习】使用yolov5对数据进行预标注
【WSL】wsl pip NewConnectionError
The structure of the earth's over 200 million proteins is fully predicted, and AlphaFold detonates the "protein universe"
[memory] grandma's song
在 Web3中网络效应
【码蹄集新手村600题】求所给数据的平方根
浅谈智能家居应用及传输方式
【运维】ssh tunneling 依靠ssh的22端口实现访问远程服务器的接口服务
管理层换血,魏建军求变,长城能告别“命悬一线”吗?
[网络]WAN技术组播
固件、驱动、软件的区别
leetcode94 -- 二叉树的中序遍历