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

Java 內存分頁器實現:假分頁 (全量加載切片) 完整代碼

     編輯:Java 相關知識

什麼是假分頁?

一次性從數據庫查出所有數據到內存 List,再在 Java 層按頁切片返回。適合數據量小、變化頻繁、需複雜排序/篩選的場景 (如後台管理幾百條配置數據)。

通用分頁器實現


public class MemoryPager {
    private final List data;
    private final int pageSize;
    
    private MemoryPager(List data, int pageSize) {
        if (data == null || data.isEmpty()) throw new IllegalArgumentException("數據不能為空");
        if (pageSize <= 0) throw new IllegalArgumentException("頁大小必須 > 0");
        this.data = Collections.unmodifiableList(new ArrayList<>(data)); // 防禦性拷貝
        this.pageSize = pageSize;
    }
    
    public static  MemoryPager of(List data, int pageSize) {
        return new MemoryPager<>(data, pageSize);
    }
    
    // 獲取指定頁 (1-based)
    public List getPage(int pageNum) {
        if (pageNum < 1) return Collections.emptyList();
        int from = (pageNum - 1) * pageSize;
        if (from >= data.size()) return Collections.emptyList();
        int to = Math.min(from + pageSize, data.size());
        return data.subList(from, to); // 視圖,無拷貝開銷
    }
    
    // 分頁元數據
    public PageInfo getPageInfo(int pageNum) {
        long total = data.size();
        int totalPages = (int) ((total + pageSize - 1) / pageSize);
        List content = getPage(pageNum);
        return new PageInfo(pageNum, pageSize, total, totalPages, content);
    }
    
    // 靜態內部類:分頁信息
    public static class PageInfo {
        public final int pageNum, pageSize, totalPages;
        public final long total;
        public final List content;
        public PageInfo(int pageNum, int pageSize, long total, int totalPages, List content) {
            this.pageNum = pageNum; this.pageSize = pageSize; this.total = total;
            this.totalPages = totalPages; this.content = content;
        }
    }
}

使用示例


public class PagerDemo {
    public static void main(String[] args) {
        // 模擬數據庫查出 12 條數據
        List allData = IntStream.rangeClosed(1, 12).boxed().collect(Collectors.toList());
        
        MemoryPager pager = MemoryPager.of(allData, 5); // 每頁 5 條
        
        System.out.println("第1頁: " + pager.getPage(1)); // [1,2,3,4,5]
        System.out.println("第2頁: " + pager.getPage(2)); // [6,7,8,9,10]
        System.out.println("第3頁: " + pager.getPage(3)); // [11,12]
        System.out.println("第4頁: " + pager.getPage(4)); // []
        
        // 獲取完整分頁信息
        MemoryPager.PageInfo info = pager.getPageInfo(2);
        System.out.printf("頁碼:%d 大小:%d 總數:%d 總頁:%d 數據:%s%n",
            info.pageNum, info.pageSize, info.total, info.totalPages, info.content);
    }
}

優缺點對比

進階:可篩選/排序的內存分頁


public class FilterablePager {
    private final List sourceData;
    
    public FilterablePager(List source) { this.sourceData = source; }
    
    public List getPage(Predicate filter, Comparator sorter, int pageNum, int pageSize) {
        Stream stream = sourceData.stream();
        if (filter != null) stream = stream.filter(filter);
        if (sorter != null) stream = stream.sorted(sorter);
        return stream.skip((long)(pageNum - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
    }
    
    public long count(Predicate filter) {
        return sourceData.stream().filter(filter).count();
    }
}

// 使用
FilterablePager pager = new FilterablePager<>(allUsers);
List page = pager.getPage(
    u -> u.getName().contains("張"),           // 篩選
    Comparator.comparing(User::getCreateTime).reversed(), // 排序
    1, 20                                      // 分頁
);

適用場景決策

選假分頁:後台配置表、字典數據、權限菜單、報表導出預覽 — 數據小、需頻繁多維篩選排序。
選真分頁:用戶列表、訂單記錄、日誌查詢、商品瀏覽 — 數據大、增長快、實時性要求高。
混合方案:Redis 緩存全量數據 (定期同步),應用層做假分頁 — 兼顧性能與靈活性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
維度假分頁 (內存)真分頁 (SQL LIMIT/OFFSET)
數據量適用< 10,000 條 (視內存)無上限
首次加載慢 (全量查詢+傳輸)快 (只查一頁)
翻頁響應極快 (內存切片)需再次查詢
排序/篩選Java 靈活實現 (Stream API)SQL 複雜、受限
數據一致性快照隔離 (加載瞬間)實時 (每頁查詢)
內存佔用高 (全量對象)低 (僅一頁)