首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 分頁實戰:內存分頁(假分頁)完整實現與適用邊界

     編輯:Java 相關知識

分頁是業務系統核心需求。本文實現一個通用的內存分頁器(假分頁),一次性查出全量數據再切片,適配所有 JDBC 數據庫,附帶適用場景與性能邊界分析。

一、 核心實現:泛型分頁器 Pager<T>

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Pager<T> {
    private final int pageSize;
    private final List<T> data;

    private Pager(List<T> data, int pageSize) {
        if (data == null || data.isEmpty()) {
            throw new IllegalArgumentException("data must be not empty!");
        }
        this.data = data;
        this.pageSize = pageSize;
    }

    public static <T> Pager<T> create(List<T> data, int pageSize) {
        return new Pager<>(data, pageSize);
    }

    /** 獲取第 pageNum 頁數據(1-based) */
    public List<T> getPagedList(int pageNum) {
        int fromIndex = (pageNum - 1) * pageSize;
        if (fromIndex >= data.size()) {
            return Collections.emptyList();
        }
        int toIndex = Math.min(pageNum * pageSize, data.size());
        return data.subList(fromIndex, toIndex);
    }

    public int getPageSize() { return pageSize; }
    public List<T> getData() { return data; }
    public int getTotalCount() { return data.size(); }
    public int getTotalPages() { return (data.size() + pageSize - 1) / pageSize; }
}

二、 使用示例

List<Integer> allData = Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12);
Pager<Integer> pager = Pager.create(allData, 10);

System.out.println(pager.getPagedList(1)); // [1..10]
System.out.println(pager.getPagedList(2)); // [11, 12]
System.out.println(pager.getPagedList(3)); // []

三、 優缺點與適用邊界

維度說明
優點① 兼容所有 JDBC 數據庫,無需寫分頁 SQL 方言
② 代碼極簡,零依賴,易維護
③ 適合數據量固定、較小(<1萬條)的字典表、配置表、後台管理列表
缺點① 全量查詢佔用大量內存,大數據量導致 OOM
② 網絡傳輸全量數據,延遲高、帶佔寬
③ 無法利用數據庫索引優化,查詢慢
④ 不支持實時數據(查詢快照)
適用場景后台管理系統的基礎數據字典、配置項、用戶列表(<5000條)、導出 Excel 前的全量獲取
禁用場景日誌表、訂單表、用戶行為表等增長型大表;高併發實時查詢接口

四、 進階優化建議

  1. 引入緩存:全量數據放入 Redis/Guava Cache,分頁器讀緩存,定時刷新。
  2. 流式分頁:JDBC ResultSet 游標模式(setFetchSize),邊讀邊發,但失去「任意跳頁」能力。
  3. 真分頁切換閾值:數據量 > 5000 或 頁數 > 50 時,強制走 SQL LIMIT/OFFSET 或 ROW_NUMBER() 真分頁。

五、 總結

內存分頁是「以空間換時間、以簡單換通用」的權衡方案。用對場景是神器,用錯場景是炸彈。建議在 Service 層封裝 PageService,內部根據數據量自動路由到「內存分頁」或「SQL 真分頁」,對上層 Controller 透明輸出統一 PageResult<T>,實現分頁策略的無感知切換。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved