- 前言
- 如何实现批量数据遍历
- 总结
有时候,我们进行大数据批量遍历检查等操作,常规的操作,我们通常需要手动实现分页形式的遍历,例如需要从数据库读取100万条记录,通常我们可能需要手动分批5000条一次进行数据读取和操作。
如何简化代码的书写,进行大数据的批量遍历。
传统的大批量的数据遍历的写法(仅作示例)
String sql="select count(1) ct from xxxx"; //通过数据库,计算总页数 int pageSize=10; for(int i=0;iString 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; public abstract class AbstractListIterator{ private List 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; } public T get() { return data.get(currentIndex); } 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 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; } public abstract List 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 {
public static List list=new ArrayList<>();
static{
for(int i=0;i<24;i++){
list.add("a"+i);
}
}
public static void main(String[] args) {
AbstractListIterator it=new AbstractListIterator(10) {
@Override
public List 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()); //获取数据
}



