Cắt đoạn dữ liệu trong Stream API với skip() và limit()

Trong bài viết này, chúng ta sẽ cùng nhau tìm hiểu về skip()limit() method. Thông thường thì 2 method này sẽ luôn đi chung với nhau nhầm cắt từng đoạn dữ liệu nhỏ từ Stream để thực hiện các tác vụ thay vì thực hiện trên tập dữ liệu lớn của Stream.

skip() method trong Stream API

skip(n) method là một intermediate operation dùng để bỏ qua qua n phần tử của Stream. Tham số n phải là số nguyên dương và nếu nó lớn hơn kích thước của Stream, skip() method sẽ trả về 1 stream rỗng.

Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    .filter(i -> i % 2 == 0)
    .skip(2)
    .forEach(i -> System.out.print(i + " "));

Output: 6 8 10

Ở ví dụ trên, chúng ta lọc ra những phần tử chia hết cho 2, và bỏ qua 2 phần tử đầu tiên là 24.

Khi Stream bắt đầu thực thi, để bỏ qua 2 phần tử đầu tiên của Stream nó phải lưu trữ trạng thái của mỗi phần tử để loại bỏ các phần tử không cần thiết, chính vì vậy skip() còn được gọi là stateful operation.

limit() method trong Stream API

limit(n) method cũng là một intermediate operation trả về một stream có kích thước nhỏ hơn hoặc bằng n. Note: Tham số n không thể là số âm.

Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    .filter(i -> i % 2 == 0)
    .limit(2)
    .forEach(i -> System.out.print(i + " "));

Output: 2 4

Cũng giống như skip(), limit() cũng là 1 statefull operation bởi vì nó cũng phải lưu trữ trạng thái của mỗi phần tử.

Kết hợp skip() và limit() 

Trong các Stream có số lượng phần tử rất lớn thì limit()skip() là 2 method vô cùng hữu dụng dùng để lấy dữ liệu theo từng đoạn nhỏ thay vì xử lý một lúc lượng lớn dữ liệu cùng lúc.

Ví dụ chúng ta sẽ xử lý từng đoạn nhỏ trong Stream sao cho mỗi lần lấy được 10 số chia hết cho 2 cho đến khi đủ 100 số thì thôi.

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

class test {
    public static void main(String[] agrs) {
        for(int i = 0; i < 100; i+=10) {
            List<Integer> integers = getEvenNumbers(i,  10);
            System.out.println(integers);
        }
    }

    private static List<Integer> getEvenNumbers(int offset, int limit) {
        return Stream.iterate(0, i -> i + 1)
                .filter(i -> i % 2 == 0)
                .skip(offset)
                .limit(limit)
                .collect(Collectors.toList());
    }

}

Note: iterate() dùng để tạo ra một Stream với số lượng phần tử vô hạn theo quy tắc mà chúng ta đặt ra. Ở trên, các phần tử sau sẽ bằng phần tử trước +1. Phần tử đầu tiên là 0.

Output:


[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
[20, 22, 24, 26, 28, 30, 32, 34, 36, 38]
[40, 42, 44, 46, 48, 50, 52, 54, 56, 58]
[60, 62, 64, 66, 68, 70, 72, 74, 76, 78]
[80, 82, 84, 86, 88, 90, 92, 94, 96, 98]
[100, 102, 104, 106, 108, 110, 112, 114, 116, 118]
[120, 122, 124, 126, 128, 130, 132, 134, 136, 138]
[140, 142, 144, 146, 148, 150, 152, 154, 156, 158]
[160, 162, 164, 166, 168, 170, 172, 174, 176, 178]
[180, 182, 184, 186, 188, 190, 192, 194, 196, 198]

Tóm lược

skip() dùng để dịch qua một đoạn n phần tử trong khi limit() giới hạn số phần tử được lấy trong kết quả trả về. Chúng ta thường sử dụng skip()limit() chung với nhau để xử lý từng đoạn dữ liệu nhỏ tăng hiệu xuất cho chương trình.

Leave a Comment

Your email address will not be published. Required fields are marked *