将一个List分页返回的操作方式

在 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 的良好兼容性。

相关推荐
小杰帅气5 小时前
STL_List简单使用
开发语言·c++·list
清辞8535 小时前
C++数据结构(链表和list)
数据结构·c++·链表
澪吟7 小时前
数据结构入门:深入理解顺序表与链表
数据结构·链表
大数据张老师7 小时前
数据结构——直接插入排序
数据结构·算法·排序算法·1024程序员节
给大佬递杯卡布奇诺8 小时前
FFmpeg 基本数据结构 AVPacket分析
数据结构·c++·ffmpeg·音视频
南方的狮子先生9 小时前
【数据结构】从线性表到排序算法详解
开发语言·数据结构·c++·算法·排序算法·1024程序员节
TheWindofFate9 小时前
C# List集合
c#·list
极客智造9 小时前
编程世界的内在逻辑:深入探索数据结构、算法复杂度与抽象数据类型
数据结构·算法·数学建模
ゞ 正在缓冲99%…10 小时前
leetcode375.猜数字大小II
数据结构·算法·leetcode·动态规划