您的位置:首页 > 其它

一个对List中的数据进行分页的工具类

2017-12-02 15:49 375 查看

在项目当中,使用分页方式分批次查询数据并渲染到页面是一种相当普遍的做法。目的是避免浏览器一次性加载过多的数据导致的页面迟缓或者崩溃。另外,在数据总量过大的情况下,一次性将内容都查询出来,查询出来的结果最初是放在内存里面的,内存也没有这么大,因此很容易导致内存不够或宕机。

往往,项目中还存在另外一种分页方式,也即内存分页。内存分页的数据总量往往是已经全部加载到内存中了的。因此可以想到,内存分页场景中的需要进行分页的数据对象并不大。 那么问题就来了?我们为什么还要进行分页,是不是画蛇添足多此一举了? 事实上有没有必要进行内存分页得具体问题具体分析。笔者在写此文之前,就已经总结出两种不得不使用内存分页机制的场景:

场景(1): 数据总量虽然不大,不足以对内存或性能造成威胁,但在使用数据进行计算的过程中产生的中间数据或最终结果总量巨大,计算产生的大量临时数据或最终结果才是可能导致性能问题的关键原因。这种情况下我们也只能将总数据划分成多个更小的批次进行处理,每次只处理一个批次,这样可以使每一个小批次产生的临时数据或计算结果不足以威胁到整个计算过程。当一个批次处理结束,临时数据被销毁之后,再进行下一批次的处理。

场景(2):一次性处理数据的耗时大于处理每一个小的批次数据的耗时:比如需要将这批数据作为参数调用某个接口,数据量大,接口提供方处理速度迟缓导致的超时无法获取数据。这种情况下,分批分多次调用接口成功的概率大于一个批次单次调用接口的概率。

场景(3):第三方库、框架本身的限制。比如sql语句的in 字句不能过长,否则会导致SQL异常。这种情况下,可能需要分多次进行查询。

为此,本人在项目中封装了一个专门对List进行分页的工具类,同时也贡献出来,希望对某些人有用!!!

(1)抽象父类:

package com.lihong.DDPush;

/**
* Created by lihong10 on 2017/11/28.
*/

import java.util.Arrays;
import java.util.List;

public class UnRepeatablePage<T> extends Page<T> {

public UnRepeatablePage(List<T> data, int pageSize) {
this(data, 1, pageSize);
}

public UnRepeatablePage(List<T> data, int pageNo, int pageSize) {
super(data, pageNo, pageSize);
}

@Override
public boolean hasNext() {
return cursor < this.totalPage;
}

@Override
public List<T> next() {
cursor++;
if (data == null) {
return null;
}

List<T> subList = null;
if (data.size() > pageSize) {
subList = data.subList(0, pageSize);
data = data.subList(pageSize, data.size());
} else {
subList = data.subList(0, data.size());
data = null;
}

return subList;
}

public void check() {
if (cursor > 0) {
throw new IllegalStateException("the operation is not permitted if for cycle or next() method has benn called before ");
}
}

@Override
public void reset() {
throw new UnsupportedOperationException("reset is not permitted !!!,if you have not, use RepeatablePage.class");
}

@Override
public void reset(int cursor) {
throw new UnsupportedOperationException("reset is not permitted !!!,if you have not, use RepeatablePage.class ");
}

public static void main(String[] args) {
List<Integer> list = Arrays.asList(new Integer[]{0, 1, 2, 3, 4, 5, 6});
int pageSize = 6;//遍历分页时候,指定分页大小是3
UnRepeatablePage<Integer> page = new UnRepeatablePage<Integer>(list, 3);

System.out.println("------------遍历前允许直接获取某一页------------------------");
System.out.println(page.getPage(2));

System.out.println("第1次遍历结果是");
for (List<Integer> li : page) { //for遍历
System.out.println(li);
}
System.out.println("------------遍历过之后,不允许直接获取某一页------------------------");
System.out.println(page.getPage(2));

page.reset();//调用reset会抛出异常,应为该子类不允许这个操作
for (List<Integer> li : page) { //for遍历
System.out.println(li);
}
}

}


(2)可重复分页的子类及示例:

package com.lihong.DDPush;

/**
* Created by lihong10 on 2017/11/28.
*/

import java.util.Arrays;
import java.util.List;

public class RepeatablePage<T> extends Page<T> {

public RepeatablePage(List<T> data, int pageSize) {
this(data, 1, pageSize);
}

public RepeatablePage(List<T> data, int currentPage, int pageSize) {
super(data, currentPage, pageSize);
}

@Override
public boolean hasNext() {
if (totalPage <= 0) {
return false;
}
return cursor < totalPage;
}

@Override
public List<T> next() {
int pageNo = this.cursor + 1;
List<T> page = getPage(pageNo);
this.cursor++;
return page;
}

public void check() {
}

public void reset() {
this.cursor = 0;
}

public void reset(int cursor) {
if (cursor < 0) {
this.cursor = 0;
} else if (cursor >= totalPage) {
this.cursor = totalPage;
} else {
this.cursor = cursor;
}
}

public static void main(String[] args) {
List<Integer> list = Arrays.asList(new Integer[]{0, 1, 2, 3, 4, 5, 6});
int pageSize = 3;//遍历分页时候,指定分页大小是3
RepeatablePage<Integer> page = new RepeatablePage<Integer>(list, pageSize);

System.out.println("------------直接获取某一页------------------------");
System.out.println(page.getPage(1));
System.out.println(page.getPage(2));
System.out.println(page.getPage(3));

System.out.println("第1次遍历结果是");
for (List<Integer> li : page) { //for遍历
System.out.println(li);
}

System.out.println("第2次遍历结果是");
page.reset();
for (List<Integer> li : page) { //遍历前调用了重置状态的reset方法,可以再次从头开始遍历
System.out.println(li);
}

System.out.println("第3次遍历结果是");
for (List<Integer> li : page) { //遍历前没有调用reset方法,遍历失败
System.out.println(li);
}
}

}


(3)不可重复分页的子类及示例:

package com.lihong.DDPush;

/**
* Created by lihong10 on 2017/11/28.
*/

import java.util.Arrays;
import java.util.List;

public class UnRepeatablePage<T> extends Page<T> {

public UnRepeatablePage(List<T> data, int pageSize) {
this(data, 1, pageSize);
}

public UnRepeatablePage(List<T> data, int pageNo, int pageSize) {
super(data, pageNo, pageSize);
}

@Override
public boolean hasNext() {
return cursor < this.totalPage;
}

@Override
public List<T> next() {
cursor++;
if (data == null) {
return null;
}

List<T> subList = null;
if (data.size() > pageSize) {
subList = data.subList(0, pageSize);
data = data.subList(pageSize, data.size());
} else {
subList = data.subList(0, data.size());
data = null;
}

return subList;
}

public void check() {
if (cursor > 0) {
throw new IllegalStateException("the operation is not permitted if for cycle or next() method has benn called befor this ");
}
}

@Override
public void reset() {
throw new UnsupportedOperationException("reset is not permitted !!!,if you have not, use RepeatablePage.class");
}

@Override
public void reset(int cursor) {
throw new UnsupportedOperationException("reset is not permitted !!!,if you have not, use RepeatablePage.class ");
}

public static void main(String[] args) {
List<Integer> list = Arrays.asList(new Integer[]{0, 1, 2, 3, 4, 5, 6});
int pageSize = 6;//遍历分页时候,指定分页大小是3
UnRepeatablePage<Integer> page = new UnRepeatablePage<Integer>(list, 3);

System.out.println("------------遍历前允许直接获取某一页------------------------");
System.out.println(page.getPage(2));

System.out.println("第1次遍历结果是");
for (List<Integer> li : page) { //for遍历
System.out.println(li);
}
System.out.println("------------遍历过之后,不允许直接获取某一页------------------------");
System.out.println(page.getPage(2));

page.reset();//调用reset会抛出异常,应为该子类不允许这个操作
for (List<Integer> li : page) { //for遍历
System.out.println(li);
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  List 分页 pagination