Java分页算法实现案例
我为你提供几种常见的Java分页实现方案:

基础内存分页(手动实现)
import java.util.ArrayList;
import java.util.List;
public class PaginationUtil {
/**
* 手动内存分页
* @param dataList 原始数据列表
* @param pageNum 当前页码(从1开始)
* @param pageSize 每页大小
* @return 当前页的数据
*/
public static <T> List<T> paginate(List<T> dataList, int pageNum, int pageSize) {
if (dataList == null || dataList.isEmpty()) {
return new ArrayList<>();
}
int totalCount = dataList.size();
int startIndex = (pageNum - 1) * pageSize;
int endIndex = Math.min(startIndex + pageSize, totalCount);
if (startIndex >= totalCount) {
return new ArrayList<>();
}
return dataList.subList(startIndex, endIndex);
}
/**
* 计算总页数
*/
public static int getTotalPages(int totalCount, int pageSize) {
return (int) Math.ceil((double) totalCount / pageSize);
}
}
完整的分页结果对象
import java.util.List;
public class PageResult<T> {
private List<T> data; // 当前页数据
private int pageNum; // 当前页码
private int pageSize; // 每页大小
private long totalCount; // 总记录数
private int totalPages; // 总页数
private boolean hasPrevious; // 是否有上一页
private boolean hasNext; // 是否有下一页
public PageResult(List<T> data, long totalCount, int pageNum, int pageSize) {
this.data = data;
this.totalCount = totalCount;
this.pageNum = pageNum;
this.pageSize = pageSize;
this.totalPages = (int) Math.ceil((double) totalCount / pageSize);
this.hasPrevious = pageNum > 1;
this.hasNext = pageNum < totalPages;
}
// Getters and Setters
public List<T> getData() { return data; }
public int getPageNum() { return pageNum; }
public int getPageSize() { return pageSize; }
public long getTotalCount() { return totalCount; }
public int getTotalPages() { return totalPages; }
public boolean isHasPrevious() { return hasPrevious; }
public boolean isHasNext() { return hasNext; }
}
使用Stream API实现分页
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class StreamPagination {
public static <T> PageResult<T> paginateWithStream(List<T> dataList, int pageNum, int pageSize) {
long totalCount = dataList.size();
List<T> pageData = dataList.stream()
.skip((pageNum - 1) * pageSize)
.limit(pageSize)
.collect(Collectors.toList());
return new PageResult<>(pageData, totalCount, pageNum, pageSize);
}
}
数据库SQL分页(以MySQL为例)
import java.sql.*;
public class DatabasePagination {
/**
* 执行分页查询
*/
public PageResult<User> queryUsersByPage(int pageNum, int pageSize) {
String countSql = "SELECT COUNT(*) FROM users";
String querySql = "SELECT * FROM users LIMIT ?, ?";
int offset = (pageNum - 1) * pageSize;
List<User> userList = new ArrayList<>();
long totalCount = 0;
try (Connection conn = getConnection();
PreparedStatement countStmt = conn.prepareStatement(countSql);
PreparedStatement queryStmt = conn.prepareStatement(querySql)) {
// 获取总记录数
ResultSet countRs = countStmt.executeQuery();
if (countRs.next()) {
totalCount = countRs.getLong(1);
}
// 查询当前页数据
queryStmt.setInt(1, offset);
queryStmt.setInt(2, pageSize);
ResultSet rs = queryStmt.executeQuery();
while (rs.next()) {
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
userList.add(user);
}
} catch (SQLException e) {
e.printStackTrace();
}
return new PageResult<>(userList, totalCount, pageNum, pageSize);
}
private Connection getConnection() throws SQLException {
// 获取数据库连接(示例代码,实际需要配置)
return DriverManager.getConnection("jdbc:mysql://localhost:3306/db", "user", "password");
}
}
MyBatis-Plus 分页(简化版)
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public PageResult<User> getUsersByPage(int pageNum, int pageSize) {
// 创建分页对象
Page<User> page = new Page<>(pageNum, pageSize);
// 执行分页查询
IPage<User> userPage = userMapper.selectPage(page, null);
// 转换为自定义分页结果
return new PageResult<>(
userPage.getRecords(),
userPage.getTotal(),
pageNum,
pageSize
);
}
}
使用示例
public class PaginationExample {
public static void main(String[] args) {
// 模拟数据
List<String> data = new ArrayList<>();
for (int i = 1; i <= 100; i++) {
data.add("Item " + i);
}
// 手动分页
List<String> pageData = PaginationUtil.paginate(data, 1, 10);
System.out.println("第1页数据: " + pageData);
// Stream分页
PageResult<String> result = StreamPagination.paginateWithStream(data, 2, 10);
System.out.println("总记录数: " + result.getTotalCount());
System.out.println("总页数: " + result.getTotalPages());
System.out.println("当前页数据: " + result.getData());
System.out.println("是否有下一页: " + result.isHasNext());
}
}
常见分页参数校验
public class PaginationValidator {
public static void validate(int pageNum, int pageSize) {
if (pageNum < 1) {
throw new IllegalArgumentException("页码必须大于0");
}
if (pageSize < 1) {
throw new IllegalArgumentException("每页大小必须大于0");
}
// 限制最大页容量,防止内存溢出
int maxPageSize = 1000;
if (pageSize > maxPageSize) {
throw new IllegalArgumentException("每页大小不能超过" + maxPageSize);
}
}
}
使用建议
- 小数据量(<1000条):可以使用内存分页
- 大数据量:必须使用数据库分页(LIMIT/OFFSET)
- ORM框架:推荐使用MyBatis-Plus或Spring Data JPA等框架的分页功能
- 性能优化:
- 避免使用OFFSET大偏移量,可使用游标分页或WHERE条件分页
- 添加必要的索引
- 考虑缓存分页结果
这就是Java中常见分页算法的实现方式,你可以根据具体场景选择合适的方案。