Java内存分页工具类

摘要:
前言 工作过程中,经常会遇到基于内存数据进行分页处理的情况,例如批量更新数据库时,集合过大需要分批更新的情况,还有例如对缓存中的集合数据进行分页获取这种情况。 本文提供了通用的内存分页工具,参考了网络上的一些代码,主要基于 subList() 方法实现,希望对你有所帮助!工具类源码在本文底部。

前言

工作过程中,经常会遇到基于内存数据进行分页处理的情况,例如批量更新数据库时,集合过大需要分批更新的情况,还有例如对缓存中的集合数据进行分页获取这种情况。
本文提供了通用的内存分页工具,参考了网络上的一些代码,主要基于 subList() 方法实现,希望对你有所帮助!工具类源码在本文底部。

本文原文链接地址:http://nullpointer.pw/Java%E5%86%85%E5%AD%98%E5%88%86%E9%A1%B5%E5%B7%A5%E5%85%B7%E7%B1%BB.html

优化前

首先来看一下正常如果要实现这些需求的话,代码的实现是怎么样的

// 分页进行批量更新
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);
        }
    }
}

结语

希望对你有用~

免责声明:文章转载自《Java内存分页工具类》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇SQLite安装和调用Thinkpad T61 on screen display 设置下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Mybatis-第N篇配置log4j1、log4j2打印执行的sql语句

1、log4j1配置    目录结构:       conf.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/myba...

坑爹的微信支付v3,其实没有那么坑

    研究微信开发一年多了,每个新接口,都会第一时间进行研究。微信支付开放很久,一直没机会接触到支付接口,等了好久终于从朋友那儿搞到了接口,从此开始了我两天多的支付接口的研究。 拿到这个接口文档的第一个想法就是这也没什么难的嘛, 和支付宝、财付通、网银在线等一些传统接口的思路逻辑都是一样的,觉得差不多最多一个下午就可以搞定,结果第一步调用统一支付接口...

1/28 对于Vue.js 中 Object.freeze( )的理解

开门见山先总结,如有错误,大佬请指正 1. const  用于单一的变量上,对于对象的属性,const 不能做到 阻止 添加、修改 对象属性 2. freeze 只要是 对象 都可以 阻止 其发生改变 ( 弥补了 const 的不足,即 不能阻止 添加 修改属性) 3. Vue 是响应式的,所以对于 data 是无法 freeze 的   ( /* 上面的...

WebSocket-java实现

一、所需jar 二、创建websocket.jsp(注意此页面链接,需要链接到自己的服务) 1 <%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%> 2 <% 3 String path = request.getContextPath...

操作select控件大全(新增、修改、删除、选中、清空、判断存在等)

1判断select选项中 是否存在Value="paraValue"的Item  2向select选项中 加入一个Item  3从select选项中 删除一个Item  4删除select中选中的项  5修改select选项中 value="paraValue"的text为"paraText"  6设置select中text="paraText"的第一个It...

easyPoi 工具类

import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.ExcelImportUtil; import cn.afterturn.easypoi.excel.entity.ExportParams; import cn.afterturn.ea...