前言
工作过程中,经常会遇到基于内存数据进行分页处理的情况,例如批量更新数据库时,集合过大需要分批更新的情况,还有例如对缓存中的集合数据进行分页获取这种情况。
本文提供了通用的内存分页工具,参考了网络上的一些代码,主要基于 subList() 方法实现,希望对你有所帮助!工具类源码在本文底部。
优化前
首先来看一下正常如果要实现这些需求的话,代码的实现是怎么样的
// 分页进行批量更新
private void batchUpdateStudent(List<Student> students) {
int limit = 100;
int size = students.size();
int m = size / limit;
int n = size % limit;
for (int i = 1; i <= m; i++) {
List<Student> list = students.subList((i - 1) * limit, i * limit);
studentDao.batchUpdate(list);
}
if (n != 0) {
List<Student> list = students.subList(m * limit, students.size());
studentDao.batchUpdate(list);
}
}
// 分页获取数据
public List<Student> pageStudents(Integer page, Integer pageSize) {
if (page < 1) {
page = 1;
}
int start = (page - 1) * pageSize;
int limit = page * pageSize;
// 从缓存中获取全量数据
List<Student> students = studentCache.getStudents();
if (CollectionUtils.isEmpty(students)) {
return new ArrayList<>();
}
if (limit > students.size()) {
limit = students.size();
}
return students.subList(start, limit), students.size();
}
可以看出方法的代码比较冗余,如果多处需要内存分页,重复代码不可避免会有很多!
优化后
// 分页进行批量更新
private void batchUpdateStudent(List<Student> students) {
RAMPager<Student> pager = new RAMPager<>(students, 100);
// 方式一:使用迭代器
Iterator<List<Student>> iterator = pager.iterator();
while (iterator.hasNext()) {
studentDao.batchUpdate(iterator.next());
}
// 方式二:使用索引
//for (int i = 1; i <= pager.getPageCount(); i++) {
// studentDao.batchUpdate(pager.page(i));
//}
}
// 分页获取数据
public List<Student> pageStudents(Integer page, Integer pageSize) {
// 从缓存中获取全量数据
List<Student> students = studentCache.getStudents();
RAMPager<Student> pager = new RAMPager<>(students, pageSize);
return pager.page(page);
}
注:如果只是分页,而不需要关注页码,使用迭代器即可;
工具类源码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* 类名称:RAMPager
* 类描述:内存分页工具
* 创建人:WeJan
* 创建时间:2019年07月22日 13:43
* Version: 1.1
*/
public class RAMPager<T> {
private List<T> data;
private int pageSize;
/**
* @param data 原始数据
* @param pageSize 每页条数
*/
public RAMPager(List<T> data, int pageSize) {
this.data = data;
this.pageSize = pageSize;
}
/**
* 获取某页数据,从第1页开始
*
* @param pageNum 第几页
* @return 分页数据
*/
public List<T> page(int pageNum) {
if (pageNum < 1) {
pageNum = 1;
}
int from = (pageNum - 1) * pageSize;
int to = Math.min(pageNum * pageSize, data.size());
if (from > to) {
from = to;
}
return data.subList(from, to);
}
/**
* 获取总页数
*/
public int getPageCount() {
if (pageSize == 0) {
return 0;
}
return data.size() % pageSize == 0 ? (data.size() / pageSize) : (data.size() / pageSize + 1);
}
/**
* 元素迭代器
*/
public Iterator<List<T>> iterator() {
return new Itr();
}
private class Itr implements Iterator<List<T>> {
int page = 1;
Itr() {
}
public boolean hasNext() {
return page <= getPageCount();
}
public List<T> next() {
int i = page;
if (i > getPageCount())
return new ArrayList<>();
page = i + 1;
return RAMPager.this.page(i);
}
}
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
System.out.println("原始数据是:" + list);
int pageSize = 2;
System.out.println("每页大小是:" + pageSize);
RAMPager<Integer> pager = new RAMPager<>(list, pageSize);
System.out.println("总页数是: " + pager.getPageCount());
System.out.println("<- - - - - - - - - - - - - ->");
// 无需感知页码情况下使用
Iterator<List<Integer>> iterator = pager.iterator();
while (iterator.hasNext()) {
List<Integer> next = iterator.next();
System.out.println("next: " + next);
}
System.out.println("<- - - - - - - - - - - - - ->");
// 需要指定页码情况使用,页码从第一页开始,且小于等于总页数!
for (int i = 1; i <= pager.getPageCount(); i++) {
List<Integer> page = pager.page(i);
System.out.println("第 " + i + " 页数据是:" + page);
}
}
}
结语
希望对你有用~