
在 Java 后端对内存 List 数据进行分页返回给前端,有几种常见的实现方式。以下是详细的解决方案:
方案一:使用 MyBatis-Plus 的 Page 对象(推荐)
java
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@RestController
@RequestMapping("/api/data")
public class DataController {
/**
* 对内存中的 List 进行分页
*/
@GetMapping("/page")
public Result<IPage<YourEntity>> getPageData(
@RequestParam(defaultValue = "1") Integer current,
@RequestParam(defaultValue = "10") Integer size) {
// 1. 获取原始数据列表(这里用模拟数据)
List<YourEntity> dataList = getDataFromMemory();
// 2. 创建分页对象
IPage<YourEntity> page = new Page<>(current, size);
// 3. 设置总记录数
page.setTotal(dataList.size());
// 4. 计算分页数据
int startIndex = (int) ((current - 1) * size);
int endIndex = Math.min(startIndex + size, dataList.size());
if (startIndex > dataList.size()) {
page.setRecords(new ArrayList<>());
} else {
List<YourEntity> pageRecords = dataList.subList(startIndex, endIndex);
page.setRecords(pageRecords);
}
return Result.success(page);
}
// 模拟从内存获取数据
private List<YourEntity> getDataFromMemory() {
List<YourEntity> list = new ArrayList<>();
for (int i = 1; i <= 100; i++) {
YourEntity entity = new YourEntity();
entity.setId((long) i);
entity.setName("Item " + i);
entity.setCreateTime(new Date());
list.add(entity);
}
return list;
}
}
方案二:自定义通用分页工具类
java
/**
* 分页工具类
*/
@Component
public class PageUtils {
/**
* 对 List 进行分页
*/
public static <T> IPage<T> paginateList(List<T> dataList, long current, long size) {
IPage<T> page = new Page<>(current, size);
page.setTotal(dataList.size());
int startIndex = (int) ((current - 1) * size);
int endIndex = Math.min(startIndex + (int) size, dataList.size());
if (startIndex >= dataList.size()) {
page.setRecords(new ArrayList<>());
} else {
List<T> pageList = dataList.subList(startIndex, endIndex);
page.setRecords(new ArrayList<>(pageList)); // 避免原List修改影响
}
return page;
}
/**
* 带排序的分页
*/
public static <T> IPage<T> paginateList(List<T> dataList, long current, long size,
Comparator<T> comparator) {
// 先排序再分页
List<T> sortedList = new ArrayList<>(dataList);
sortedList.sort(comparator);
return paginateList(sortedList, current, size);
}
}
// 控制器中使用
@RestController
@RequestMapping("/api/data")
public class DataController {
@GetMapping("/page")
public Result<IPage<YourEntity>> getPageData(
@RequestParam(defaultValue = "1") Integer current,
@RequestParam(defaultValue = "10") Integer size,
@RequestParam(required = false) String sortField) {
List<YourEntity> dataList = getDataFromMemory();
// 可选:添加添加排序逻辑
if ("name".equals(sortField)) {
return Result.success(PageUtils.paginateList(dataList, current, size,
Comparator.comparing(YourEntity::getName)));
}
return Result.success(PageUtils.paginateList(dataList, current, size));
}
}
方案三:封装统一响应对象
java
/**
* 统一的响应结果包装类
*/
@Data
public class Result<T> implements Serializable {
private Boolean success;
private Integer code;
private String message;
private T data;
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setSuccess(true);
result.setCode(200);
result.setMessage("操作成功");
result.setData(data);
return result;
}
}
/**
* 自定义分页响应对象(如果不依赖 MyBatis-Plus)
*/
@Data
public class CustomPage<T> {
private Long current; // 当前页
private Long size; // 每页大小
private Long total; // 总记录数
private Long pages; // 总页数
private List<T> records; // 数据列表
public CustomPage(Long current, Long size, Long total, List<T> records) {
this.current = current;
this.size = size;
this.total = total;
this.pages = (total + size - 1) / size; // 计算总页数
this.records = records;
}
/**
* 从 List 创建分页对象
*/
public static <T> CustomPage<T> of(List<T> dataList, long current, long size) {
long total = dataList.size();
long startIndex = (current - 1) * size;
long endIndex = Math.min(startIndex + size, total);
List<T> pageRecords;
if (startIndex >= total) {
pageRecords = new ArrayList<>();
} else {
pageRecords = new ArrayList<>(
dataList.subList((int) startIndex, (int) endIndex)
);
}
return new CustomPage<>(current, size, total, pageRecords);
}
}
方案四:结合 Stream API 的高级用法
java
@Service
public class DataService {
/**
* 使用 Stream API 进行复杂分页
*/
public IPage<YourEntity> getComplexPageData(long current, long size,
Map<String, Object> filters) {
List<YourEntity> allData = getDataFromMemory();
// 流式处理:过滤 -> 排序 -> 分页
List<YourEntity> filteredData = allData.stream()
.filter(item -> filterCondition(item, filters)) // 自定义过滤条件
.sorted(Comparator.comparing(YourEntity::getCreateTime).reversed())
.collect(Collectors.toList());
return PageUtils.paginateList(filteredData, current, size);
}
/**
* 多条件动态查询
*/
public IPage<YourEntity> dynamicQueryPage(List<YourEntity> dataList,
long current, long size,
DynamicQuery query) {
Stream<YourEntity> stream = dataList.stream();
// 动态添加过滤条件
if (StringUtils.hasText(query.getKeyword())) {
stream = stream.filter(item ->
item.getName().contains(query.getKeyword()));
}
if (query.getStartDate() != null) {
stream = stream.filter(item ->
!item.getCreateTime().before(query.getStartDate()));
}
List<YourEntity> filteredList = stream.collect(Collectors.toList());
return PageUtils.paginateList(filteredList, current, size);
}
private boolean filterCondition(YourEntity item, Map<String, Object> filters) {
// 实现你的过滤逻辑
return true;
}
}
前端调用示例
html
// Vue/React 调用示例
const getPageData = async (page = 1, page pageSize = 10) => {
try {
const response = await axios.get('/api/data/page', {
params: {
current: page,
size: pageSize
}
});
const pageInfo = response.data.data;
console.log('当前页:', pageInfo.current);
console.log('每页大小:', pageInfo.size);
console.log('总记录数:', pageInfo.total);
console.log('总页数:', pageInfo.pages);
console.log('数据列表:', pageInfo.records);
} catch (error) {
console.error('请求失败:', error);
}
};
关键要点总结
1、性能考虑:对于大数据集,建议缓存分页计算结果
2、线程安全:如果源 List 可能被并发修改,需要加锁或使用副本
3、空值处理:处理好边界情况(如超出范围的页码)
4、灵活性:可根据需要添加排序、过滤等功能
推荐使用方案一或方案二,它们结构清晰且易于维护,同时保持了与 MyBatis-Plus 的良好兼容性。