limit & skip

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 5 min

TL;DR

  • limit(n) restricts the stream to process only the first n elements. It is a short-circuiting intermediate operation.
  • skip(n) discards the first n elements of the stream and processes the rest.
  • They are often used together to implement pagination.

Concept

When processing large streams (or infinite streams), you rarely need all the data.

limit(n) acts as a circuit breaker. As soon as n elements have passed through the pipeline and reached the terminal operation, limit signals the stream to stop processing immediately.

skip(n) is a stateful operation. It keeps a counter; it simply swallows the first n elements that arrive, doing nothing with them. Once the counter reaches n, it allows all subsequent elements to pass through.

Examples

import java.util.stream.Stream;

public class LimitSkipExample {
    public static void main(String[] args) {
        
        // --- 1. Limit (Short-circuiting an infinite stream) ---
        // Generates an infinite stream of 1s. Limit stops it at 5.
        Stream.generate(() -> 1)
            .limit(5)
            .forEach(System.out::print); // 11111
        System.out.println();
        
        
        // --- 2. Skip ---
        Stream.of(1, 2, 3, 4, 5)
            .skip(3)
            .forEach(System.out::print); // 45
        System.out.println();
        
        
        // --- 3. Pagination (Skip + Limit) ---
        // E.g., Page 2, Page size 10 -> skip 10, limit 10
        int pageNumber = 2; // 1-indexed
        int pageSize = 3;
        
        Stream.of("A", "B", "C", "D", "E", "F", "G")
            .skip((pageNumber - 1) * pageSize) // skip 3
            .limit(pageSize)                   // take next 3
            .forEach(System.out::print);       // DEF
    }
}

Interview Questions

Q: Is the order of skip and limit important?
A: Yes, absolutely. stream.skip(5).limit(2) means “discard the first 5 elements, then give me the next 2”. (Outputs elements 6 and 7).
stream.limit(2).skip(5) means “keep only the first 2 elements, then discard the first 5 of those”. This results in an empty stream.

Q: Why is limit() so important for Stream.generate() and Stream.iterate()?
A: generate and iterate create infinite streams. Because terminal operations like forEach or collect pull data until the stream is empty, calling them on an infinite stream will cause an infinite loop (and eventually an OutOfMemoryError). limit() acts as the short-circuiting mechanism to terminate the infinite stream.