Written By : Nguyễn Văn Linh
Gmail : Linhthai130100@gmail.com

1. Giới thiệu

Trong bài viết hôm nay tôi sẽ giới thiệu đến các bạn 2 phương thức skip()limit() trong stream java 8 và những nổi bật điểm giống nhau và khác nhau giữa 2 phương thức này.

Mặc dù hai thao tác này thoạt nhìn có thể khá giống nhau, nhưng chúng thực sự hoạt động rất khác nhau và không thể hoán đổi cho nhau. Trên thực tế, chúng bổ sung cho nhau và có thể tiện dụng khi sử dụng cùng nhau. Hãy tiếp tục đọc để tìm hiểu thêm về chúng.

Vậy khi nào chúng ta sử dụng skip() , khi nào chúng ta sử dụng limit()

Sau đây tôi sẽ hướng dẫn cho các biết cách sử dụng của 2 phương thức này

Link bài viết tham khảo :Java 8 Stream Skip() and Limit()

2. Phương thức Skip()

Phương thức skip(n) là một phép toán trung gian loại bỏ n phần tử đầu tiên của một luồng . Tham số n không được âm và nếu nó cao hơn kích thước của luồng, thì skip() trả về một luồng trống.
Hãy xem ví dụ :

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 + " "));

Trong luồng này, chúng tôi chọn các số chẵn của luồng nhưng chúng tôi bỏ qua hai số đầu tiên. Do đó, kết quả của chúng tôi là:

6 8 10

Khi luồng này được thực thi, forEach bắt đầu yêu cầu các mục. Khi nó được skip() , hoạt động này biết rằng hai mục đầu tiên phải bị loại bỏ, vì vậy nó không thêm chúng vào luồng kết quả. Sau đó, nó tạo và trả về một luồng với các mục còn lại.

Để làm điều này, phép toán skip() phải giữ trạng thái của các phần tử được nhìn thấy tại mỗi thời điểm. Vì lý do này, chúng tôi nói rằng skip() là một hoạt động trạng thái .

3. Phương thức Limit()

Phương thức limit(n) là một thao tác trung gian khác trả về một luồng không dài hơn kích thước được yêu cầu . Như trước đây, tham số n không được âm.

Hãy sử dụng nó trong một ví dụ:

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 + " "));

Trong trường hợp này, chúng tôi chỉ chọn hai số chẵn từ luồng int :

2 4

Giống như trường hợp của phép toán skip() , limit() cũng là một hoạt động trạng thái vì nó phải giữ trạng thái của các mục đang được chọn.

Nhưng không giống như skip() , sử dụng toàn bộ luồng, ngay khi limit() đạt đến số lượng mục tối đa, nó sẽ không sử dụng thêm bất kỳ mục nào và chỉ trả về luồng kết quả. Do đó, chúng tôi nói rằng limit() là một hoạt động đoản mạch .

Khi làm việc với các luồng vô hạn, limit() có thể rất hữu ích để cắt bớt một luồng thành một luồng hữu hạn:

Stream.iterate(0, i -> i + 1)
    .filter(i -> i % 2 == 0)
    .limit(10)
    .forEach(System.out::println);

4. Kết hợp Skip() và Limit()

Như chúng ta đã đề cập trước đó, các thao tác bỏ qua và giới hạn là bổ sung cho nhau và nếu chúng ta kết hợp chúng, chúng có thể rất hữu ích trong một số trường hợp.

Hãy tưởng tượng rằng chúng tôi muốn sửa đổi ví dụ trước của chúng tôi để nó nhận được các số chẵn theo lô mười. Chúng ta có thể thực hiện điều đó đơn giản bằng cách sử dụng cả hai loại skip()limit() trên cùng một luồng:

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());
}

Như chúng ta thấy, chúng ta có thể phân trang thông qua luồng khá dễ dàng với phương pháp này. Mặc dù đây là một phân trang rất đơn giản, chúng ta có thể thấy điều này có thể mạnh mẽ như thế nào khi cắt một luồng.

5. Kết luận

Trong bài viết ngắn gọn này, chúng tôi đã chỉ ra những điểm giống và khác nhau của các phương thức skip()limit() của Java Stream API. Chúng tôi cũng đã triển khai một số ví dụ đơn giản để chỉ ra cách chúng tôi có thể sử dụng các phương pháp này.