Stream分頁詳解

一、stream分頁排序

Stream是Java8中新增的API,用於支持函數式編程。其提供了大量的方法和操作,其中很重要的一種就是排序。在分頁操作中,排序也佔據着非常重要的地位。

排序可以通過sorted()方法實現。例如:

List list = Arrays.asList(1, 5, 3, 9, 7, 6);
List sortedList = list.stream()
                                 .sorted()
                                 .collect(Collectors.toList());

上述代碼中,我們首先將一個整數列錶轉換成Stream,然後使用sorted()方法對列表進行升序排序,最後通過collect()方法將結果轉換為List。

二、stream分為幾個區

在進行分頁操作時,我們需要將數據分為多個區,以方便進行分頁處理。Stream提供了skip()limit()方法可以幫助我們實現這一點。

skip()方法用於跳過前n個元素,返回剩下的元素,代碼如下:

List list = Arrays.asList(1, 2, 3, 4, 5, 6);
List result = list.stream()
                            .skip(2)
                            .collect(Collectors.toList());

上述代碼中,我們將一個整數列錶轉換成Stream,然後使用skip()方法跳過前兩個元素,返回剩下的四個元素。

limit()方法用於截取Stream的前n個元素,代碼如下:

List list = Arrays.asList(1, 2, 3, 4, 5, 6);
List result = list.stream()
                            .limit(3)
                            .collect(Collectors.toList());

上述代碼中,我們將一個整數列錶轉換成Stream,然後使用limit()方法截取前三個元素。

三、stream分頁查詢

Stream可以幫助我們實現分頁操作。以MySQL數據庫為例,我們可以通過limit()offset()方法實現分頁查詢。

假設我們有一個包含1000條記錄的用戶表,我們想要查詢第11到20條記錄,代碼如下:

int pageNum = 2;    // 第二頁
int pageSize = 10;  // 每頁10條記錄
List userList = userDao.getAllUsers();  // 獲取所有用戶
List result = userList.stream()
                            .skip((pageNum - 1) * pageSize)
                            .limit(pageSize)
                            .collect(Collectors.toList());

上述代碼中,我們先獲取了所有的用戶記錄,並將其轉換成Stream。然後使用skip()方法跳過前10條記錄(第一頁的記錄),使用limit()方法截取10條記錄,即第11到20條記錄。

四、stream分頁性能問題

在進行分頁操作時,我們需要避免出現性能問題。一般而言,使用limit()skip()方法進行分頁操作,並不會影響整個查詢的性能。

但是,在對大數據量進行分頁查詢時(例如上百萬條記錄),由於Stream是在內存中進行操作的,會導致內存溢出的問題。此時,我們需要考慮使用分頁查詢的擴展庫,例如Mybatis-PageHelper。

五、stream分頁1000條數據

在分頁中,我們通常會將數據分為若干頁。如果我們想要將數據分為1000條一組,則可以使用partition()方法實現,代碼如下:

List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
int pageSize = 1000;

List<List> result = IntStream.range(0, (list.size() + pageSize - 1) / pageSize)
                                      .mapToObj(i -> list.subList(i * pageSize, Math.min(pageSize * (i + 1), list.size())))
                                      .collect(Collectors.toList());

上述代碼中,我們將一個包含9個元素的整數列表拆分為每1000條一組的集合。使用IntStream.range()方法生成了一系列的數字範圍,然後將列表按照指定的大小進行拆分,使用collect()方法將結果轉換為List。

六、stream流分頁

除了使用limit()skip()方法進行分頁操作外,我們還可以使用流分頁技術。

在實現流分頁時,我們需要自定義一個類,實現Spliterator接口,代碼如下:

public class StreamPager implements Spliterator {
    // 分頁大小
    private final int pageSize;

    // 數據源
    private final Spliterator source;

    // 當前頁數
    private int currentPage = 0;

    // 總頁數
    private long totalPages = Long.MAX_VALUE;

    // 當前頁記錄數
    private int currentPageSize = 0;

    // 當前頁數據
    private List currentPageData;

    public StreamPager(Spliterator source, int pageSize) {
        this.pageSize = pageSize;
        this.source = source;
    }

    @Override
    public boolean tryAdvance(Consumer action) {
        if (currentPage == 0) {  // 第一頁
            currentPageData = new ArrayList(pageSize);
            while (source.tryAdvance((T t) -> {
                currentPageData.add(t);  // 將記錄添加到當前頁數據
                currentPageSize++;
            }) && currentPageSize < pageSize) ;
            totalPages = (source.estimateSize() + pageSize - 1) / pageSize;  // 計算總頁數
        }

        if (currentPageData.isEmpty()) {  // 沒有下一頁
            return false;
        }

        action.accept(currentPageData.remove(0));  // 取出記錄
        currentPageSize--;
        if (currentPageSize == 0 && currentPage < totalPages) {  // 進入下一頁
            currentPage++;
            currentPageSize = 0;
        }

        return true;
    }

    @Override
    public Spliterator trySplit() {
        return null;
    }

    @Override
    public long estimateSize() {
        return totalPages * pageSize;
    }

    @Override
    public int characteristics() {
        return source.characteristics();
    }
}

代碼中,我們定義了一個StreamPager類,實現了Spliterator接口。該類用於對數據進行分頁操作。

我們可以使用StreamSupport.stream()方法創建一個Stream,並將StreamPager作為參數傳入。例如:

List userList = userDao.getAllUsers();  // 獲取所有用戶
Stream userStream = StreamSupport.stream(new StreamPager(userList.spliterator(), 10), false);
List page1 = userStream.collect(Collectors.toList());  // 獲取第一頁數據

上述代碼中,我們首先獲取所有的用戶記錄,並將其轉換為Stream。然後使用自定義的StreamPager類進行分頁操作,設置分頁大小為10。最後通過collect()方法將結果轉換為List。

七、list stream分頁

除了使用Stream對象進行分頁外,我們還可以使用List對象實現分頁操作。例如:

List userList = userDao.getAllUsers();  // 獲取所有用戶
List page1 = userList.subList(0, 10);  // 獲取第一頁數據

上述代碼中,我們首先獲取所有的用戶記錄,然後使用subList()方法將其拆分為前10條記錄,得到第一頁數據。

八、stream分組

在對數據進行分頁前,我們通常需要將其進行分組。Stream提供了groupingBy()方法可以幫助我們實現分組操作。

例如,我們有一份包含學生成績的列表,並按照班級進行分組,代碼如下:

Map<Integer, List> studentMap = studentList.stream()
                                                     .collect(Collectors.groupingBy(Student::getClassId));

上述代碼中,我們將學生列錶轉換成Stream,並使用groupingBy()方法將其按照班級(classId屬性)進行分組,最終得到一個Map,其中Key為班級編號,Value為學生列表。

九、stream流分組

與流分頁類似,我們可以自定義一個類,實現Spliterator接口,來實現流分組操作。

例如,我們有一份包含學生成績的列表,並按照班級進行分組,每組最多包含10條記錄,代碼如下:

public class StreamGrouper implements Spliterator<Map.Entry<K, List>> {
// 分組方法
private static final BiConsumer<Map<Object, List>, Object> GROUPER = (map, item) -> {
K key = (K) ((Object[]) item)[0];
T value = (T) ((Object[]) item)[1];
map.computeIfAbsent(key, k -> new ArrayList()).add(value);
};

private final Spliterator source;
private final Function classifier;
private final int groupSize;
private final Map<Object, List> buffer = new HashMap();
private long totalGroups = Long.MAX_VALUE;
private Long bufferSize;

public StreamGrouper(Spliterator source, Function classifier, int groupSize) {
this.source = source;
this.classifier = classifier;
this.groupSize = groupSize;
}

@Override
public boolean tryAdvance(Consumer<? super Map.Entry<K, List>> action) {
Object[] currentPair = buffer.isEmpty() ? null : buffer.entrySet().iterator().next().getValue().remove(0);
while (currentPair == null) {
if (bufferSize != null && buffer.size() >= bufferSize) {
drainBuffer(action);
return true;
}

if (!source.tryAdvance(item -> GROUPER.accept(buffer, new Object[]{classifier.apply(item), item}))) {
if (!buffer.isEmpty()) {
drainBuffer(action);
return true;
}
return false;
}

currentPair = buffer.isEmpty() ? null : buffer.entrySet().iterator().next().getValue().remove(0);
}

action.accept(new AbstractMap.SimpleImmutableEntry((K) currentPair[0], bufferMerge((K) currentPair[0], currentPair[1])));
return true;
}

private void drainBuffer(Consumer<? super Map.Entry<K, List>> action) {
Map.Entry<Object, List> head = buffer.entrySet().iterator().next();
K key = (K) head.getKey();
action.accept(new AbstractMap.SimpleImmutableEntry(key, bufferMerge(key, head.getValue())));

buffer.remove(key);
}

private List bufferMerge(K key, Object value) {
List bufferGroup = buffer.get(key);
List result = new ArrayList(bufferGroup.size() + 1);
result.add((T) value);
result.addAll((List) bufferGroup);
return result;
}

@Override
public Spliterator<Map.Entry<K, List>> trySplit() {
if (totalGroups <= 1) {
return null;
}

Spliterator prefix = source.trySplit();
if (prefix == null) {
return null;
}

updateTotalGroups();

long halfGroupSize = totalGroups / 2 / groupSize * groupSize;
if (halfGroupSize == 0) {
return null;
}

currentBufferSize = Math.min(bufferSize, totalGroups / (2 * groupSize));
while (bufferSize == null && currentBufferSize > 0) {
Map.Entry<Object, List> head = buffer.entrySet().iterator().next();
if (head.getValue().size() >= currentBufferSize * groupSize) {
break;
}

if (!prefix.tryAdvance(item -> GROUPER.accept(buffer, new Object[]{classifier.apply(item), item}))) {
break;
}

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/282621.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-22 08:05
下一篇 2024-12-22 08:05

相關推薦

  • jQuery Datatable分頁中文

    jQuery Datatable是一個非常流行的數據表插件,它可以幫助您快速地在頁面上創建搜索、過濾、排序和分頁的數據表格。不過,它的默認設置是英文的,今天我們就來探討如何將jQu…

    編程 2025-04-29
  • 如何使用integratecustomerdata.stream().filter(c->{ if (collectionutil.isnotempty(

    本文將詳細介紹如何在Java編程中使用integratecustomerdata.stream().filter(c->{ if (collectionutil.isnote…

    編程 2025-04-28
  • uniapp分頁第二次請求用法介紹

    本文將從多個方面對uniapp分頁第二次請求進行詳細闡述,並給出對應的代碼示例。 一、請求參數的構造 在進行分頁請求時,需要傳遞的參數體包含當前頁碼以及每頁顯示的數據量。對於第二次…

    編程 2025-04-27
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁盤中。在執行sync之前,所有的文件系統更新將不會立即寫入磁盤,而是先緩存在內存…

    編程 2025-04-25
  • 神經網絡代碼詳解

    神經網絡作為一種人工智能技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網絡的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網絡模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分布式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變量讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web服務器。nginx是一個高性能的反向代理web服務器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25

發表回復

登錄後才能評論