Post

Java Stream skip()과 limit()

1. skip() 메소드

skip(n) 메서드는 스트림의 처음 n개 요소를 삭제하는 중간 작업 이다. n 매개 변수는 음수일 수 없으며 스트림 크기보다 큰 경우 skip()은 빈 스트림을 반환한다.

예이다.

1
2
3
4
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 + " "));

이 스트림에서는 스트림의 짝수를 선택하지만 처음 두 개는 건너뛴다. 따라서 결과는 다음과 같다.

1
6 8 10

이 스트림이 실행되면 forEach가 항목을 요청하기 시작한다. skip()에 도달하면 이 작업은 처음 두 항목을 버려야 한다는 것을 알고 있으므로 결과 스트림에 추가하지 않는다. 그런 다음 나머지 항목이 포함된 스트림을 생성하고 반환한다.

이를 위해서는 skip() 작업이 매 순간 표시되는 요소의 상태를 유지해야 한다. 이러한 이유로 skip()을 상태 저장 작업이라고 한다.

2. limit() 메소드

limit(n) 메소드는 요청된 크기보다 길지 않은 스트림을 반환하는 또 다른 중간 작업이다. 이전과 마찬가지로 n 매개변수는 음수일 수 없다.

예이다.

1
2
3
4
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 + " "));

이 경우 int 스트림에서 단 두 개의 짝수만 선택한다.

1
2 4

skip() 작업의 경우와 마찬가지로, limit()도 선택되는 항목의 상태를 유지해야 하기 때문에 상태 저장 작업이다.

그러나 전체 스트림을 소비하는 skip()과 달리, limit()은 최대 항목 수에 도달 하자마자 더 이상 항목을 소비하지 않고 결과 스트림을 반환한다. 따라서 limit()이 단락 연산이라고 한다.

무한 스트림으로 작업할 때, limit()는 스트림을 유한 스트림으로 자르는데 매우 유용할 수 있다.

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

이 예에서는 무한한 숫자 스트림을 10개의 짝수만 포함하는 스트림으로 자른다.

3. skip()과 limit() 결합

skiplimit 작업은 상호 보완적이며 이를 결합하면 경우에 따라 매우 도움이 될 수 있다.

이전 예제를 수정하여 10개의 일괄 처리에서 짝수를 가져오고 싶다고 가정한다. 동일한 스트림에서 skip()limit()을 모두 사용하면 간단하다.

1
2
3
4
5
6
7
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());
}

보시다시피, 이 방법을 사용하면 스트림을 통해 아주 쉽게 페이지를 매길 수 있다. 이는 매우 단순한 페이지 매김이지만 스트림을 분할할 때 이것이 얼마나 강력한지 알 수 있다.

[출처 및 참고]

This post is licensed under CC BY 4.0 by the author.