主要代码:
public static PagingModel getPagingModel(int page, int pageSize, int count) {
// 第一个被dataCount整除的位置(0 ~ pageSize之间的值),也就是firstCount的值
int firstValue = 0,
// 最后一个被dataCount整除的位置(0 ~ pageSize之间的值),被pageSize减去后,就是lastCount的值
lastValue = 0;
// 数据库起始索引
int offset = 0,
// 数据库查询条数
limit = 0,
// 倍数,用于统计可显示全部天数的数据(表现为dataCount条新数据)的元数据条数
times = 0,
// 当上一页有数据未完全显示时,firstCount为未完全显示的剩余条数
firstCount = 0,
// 当本页有数据不能被完全显示时,lastCount为这些数据应显示的条数
lastCount = 0,
// 开始行数
startRow = 0,
// 结束行数
endRow = 0;
// 此公式原用于计算数据库中的起始索引,即LIMIT offset, count; 现由于数据总条数的变动,只能作为临时参考。
int index = (page - 1) * pageSize;
// 原本为数据库中根据LIMIT offset, count;查询到的第一行的行号。
startRow = index + 1;
// 原本为数据库中根据LIMIT offset, count;查询到的最后一行的行号。
endRow = page * pageSize;
/**
* 计算开始行到结束行之间(包含),递增,第一个能被dataCount整除的位置(索引从1开始),可直接作为firstCount的值
*/
for (int i = startRow, j = 1; i <= endRow; i++, j++) {
if (i % count == 0) {
firstValue = j;
break;
}
}
/**
* 计算结束行到开始行之间(包含),递减,第一个能被dataCount整除的位置(索引从pageSize开始)
*/
for (int i = endRow, j = pageSize; i >= startRow; i--, j--) {
if (i % count == 0) {
lastValue = j;
break;
}
}
firstCount = firstValue; // 赋值
lastCount = pageSize - lastValue; // 赋值
times = (lastValue - firstValue) / count; // 计算倍数
/*
* 如果firstCount和dataCount相等,就将它放入可被完全显示的数目中
*/
if (firstCount == count) {
firstCount = 0;
times++;
}
// 因为总数据多了dataCount倍,现有的offset应该要在原有的基础上除以dataCount
offset = index / count;
// 计算limit的条数
limit = (firstCount > 0 ? 1 : 0) + times + (lastCount > 0 ? 1 : 0);
System.out.println("firstValue=" + firstValue + "&lastValue=" + lastValue + "&startRow=" + startRow + "&endRow="
+ endRow + "&page=" + page + "&firstCount=" + firstCount + "×=" + times + "&lastCount=" + lastCount
+ "&offset=" + offset + "&limit=" + limit);
PagingModel model = new PagingModel();
model.setFirst(firstCount);
model.setTimes(times);
model.setLast(lastCount);
model.setOffset(offset);
model.setLimit(limit);
return model;
}
模型
public static class PagingModel {
private int first;
private int times;
private int last;
private int offset;
private int limit;
public int getFirst() {
return first;
}
public void setFirst(int first) {
this.first = first;
}
public int getTimes() {
return times;
}
public void setTimes(int times) {
this.times = times;
}
public int getLast() {
return last;
}
public void setLast(int last) {
this.last = last;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
}
测试:
public static void main(String[] args) {
int page = 1, // 当前页数
pageSize = 20, // 每页显示数据
days = 7; // 查询天数
int count = days; // 每条元数据对应新数据条数
int metadataCount = 50;// 假设数据库中有50条数据
// 每条数据库中的元数据都会产生dataCount条数据,即总条数为totalCount = metadataCount * count
int totalCount = metadataCount * count;
// 计算总页数
int totalPage = (totalCount + pageSize - 1) / pageSize;
PagingModel pagingModel;
List<ResultModel> subMetadatas;
List<ResultModel> results;
for (page = 1; page <= totalPage; page++) {
pagingModel = getPagingModel(page, pageSize, count);
List<ResultModel> metadatas = new ArrayList<>(metadataCount);
ResultModel resultModel;
for (int i = 0; i < metadataCount; i++) {
resultModel = new ResultModel();
resultModel.setId(10000 + i);
metadatas.add(resultModel);
}
int fromIndex = pagingModel.getOffset();
int toIndex = pagingModel.getOffset() + pagingModel.getLimit();
if (toIndex > metadataCount) {
toIndex = metadataCount;
}
// 慎用subList
subMetadatas = metadatas.subList(fromIndex, toIndex);
results = new ArrayList<>(pageSize);
int size = subMetadatas.size();
if (pagingModel.getFirst() > 0 && size > 0) {
results.addAll(createFirstData(count, pagingModel.getFirst(), subMetadatas.get(0)));
subMetadatas.remove(0); // 直接从集合里删除更方便计算
}
int times = pagingModel.getTimes();
size = subMetadatas.size();
if (times > 0 && size > 0) {
// 慎用subList
if (times > size) {
times = size;
}
results.addAll(createMiddleData(count, subMetadatas.subList(0, times)));
// 慎用subList
if (times >= size) {
subMetadatas.clear();
}
}
size = subMetadatas.size();
if (pagingModel.getLast() > 0 && size > 0) {
results.addAll(createLastData(pagingModel, subMetadatas.get(size - 1)));
subMetadatas.remove(size - 1); // 直接从集合里删除更方便计算
}
System.out.println("*********************第" + page + "页数据***************************");
System.out.println("序号\tID\t日期");
int i = 1;
for (ResultModel model : results) {
System.out.println((i++) + "\t" + model);
}
System.out.println("***********************结束************************");
System.out.println();
}
}
static List<ResultModel> createFirstData(int count, int firstCount, ResultModel first) {
List<ResultModel> results = new ArrayList<>(firstCount);
// 并依次往前取昨天,前天的时间
LocalDate localDate = LocalDate.now().minusDays(count - firstCount);
ResultModel resultModel = null;
for (int i = 0; i < firstCount; i++) {
resultModel = first.clone();
resultModel.setDate(DateTimeFormatter.ISO_DATE.format(localDate.minusDays(i)));
results.add(resultModel);
}
return results;
}
static List<ResultModel> createMiddleData(int count, List<ResultModel> datas) {
List<ResultModel> results = new ArrayList<>(datas.size());
// 显示全部数据,日期是当天开始由后往前排序
LocalDate localDate = LocalDate.now();
ResultModel resultModel = null;
for (ResultModel model : datas) {
for (int i = 0; i < count; i++) {
resultModel = model.clone();
resultModel.setDate(DateTimeFormatter.ISO_DATE.format(localDate.minusDays(i)));
results.add(resultModel);
}
}
return results;
}
static List<ResultModel> createLastData(PagingModel pagingModel, ResultModel last) {
List<ResultModel> results = new ArrayList<>(pagingModel.getLast());
// last为末尾元数据截取,日期是当天开始由后往前排序
LocalDate localDate = LocalDate.now();
ResultModel resultModel = null;
for (int i = 0; i < pagingModel.getLast(); i++) {
resultModel = last.clone();
resultModel.setDate(DateTimeFormatter.ISO_DATE.format(localDate.minusDays(i)));
results.add(resultModel);
}
return results;
}
public static class ResultModel implements Cloneable {
private int id;
private String date;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
@Override
protected ResultModel clone() {
try {
return (ResultModel) super.clone();
} catch (CloneNotSupportedException e) {
ResultModel model = new ResultModel();
model.id = id;
model.date = date;
return model;
}
}
@Override
public String toString() {
return id + "\t" + date;
}
}