TheAlgorithms/Java · error · IllegalArgumentException

Sample size cannot exceed stream size.

Error message

Sample size cannot exceed stream size.

What it means

Thrown by ReservoirSampling.sample(stream, sampleSize) when sampleSize > stream.length. The algorithm fills the reservoir with the first sampleSize elements, so requesting more than the stream has is invalid. NOTE: this is the ONLY guard — a null stream throws NPE elsewhere, and a negative sampleSize passes this check but later throws IllegalArgumentException from ArrayList(-1) capacity.

Source

Thrown at src/main/java/com/thealgorithms/randomized/ReservoirSampling.java:36

 * @see <a href="https://en.wikipedia.org/wiki/Reservoir_sampling">Reservoir Sampling - Wikipedia</a>
 */
public final class ReservoirSampling {

    // Prevent instantiation of utility class
    private ReservoirSampling() {
        throw new UnsupportedOperationException("Utility class");
    }

    /**
     * Selects k random elements from a stream using reservoir sampling.
     *
     * @param stream     The input stream as an array of integers.
     * @param sampleSize The number of elements to sample.
     * @return A list containing k randomly selected elements.
     */
    public static List<Integer> sample(int[] stream, int sampleSize) {
        if (sampleSize > stream.length) {
            throw new IllegalArgumentException("Sample size cannot exceed stream size.");
        }

        List<Integer> reservoir = new ArrayList<>(sampleSize);
        Random rand = new Random();

        for (int i = 0; i < stream.length; i++) {
            if (i < sampleSize) {
                reservoir.add(stream[i]);
            } else {
                int j = rand.nextInt(i + 1);
                if (j < sampleSize) {
                    reservoir.set(j, stream[i]);
                }
            }
        }

        return reservoir;
    }

View on GitHub (pinned to fdfb9a395b)

Solutions

  1. Cap sampleSize to stream.length before calling: sampleSize = Math.min(sampleSize, stream.length).
  2. If you need exactly sampleSize elements, ensure your stream has at least that many upstream.
  3. Also guard stream != null and sampleSize >= 0 at the caller — the method does not.

Example fix

// before
List<Integer> s = ReservoirSampling.sample(stream, k); // k may exceed stream.length

// after
int k = Math.min(requestedK, stream == null ? 0 : stream.length);
List<Integer> s = ReservoirSampling.sample(stream, k);
Defensive patterns

Strategy: validation

Validate before calling

if (stream == null) throw new IllegalArgumentException("stream must not be null");
if (sampleSize < 0) throw new IllegalArgumentException("sampleSize must be >= 0");
int k = Math.min(sampleSize, stream.length);
List<Integer> s = ReservoirSampling.sample(stream, k);

Type guard

static boolean validReservoirParams(int[] stream, int sampleSize) {
    return stream != null && sampleSize >= 0 && sampleSize <= stream.length;
}

Try / catch

try {
    List<Integer> s = ReservoirSampling.sample(stream, sampleSize);
} catch (IllegalArgumentException | NullPointerException e) {
    logger.warn("Reservoir sampling rejected stream/sampleSize");
}

Prevention

When it happens

Trigger: sample(new int[]{1,2,3}, 5) (sampleSize 5 > length 3); computing sampleSize from a percentage that rounds up beyond the stream size.

Common situations: Asking for k=10 samples from a stream of 7; user-configured sample count larger than the available data; percentage-based sampling (sampleSize = ceil(pct * n)) that exceeds n.

Related errors


AI-assisted analysis of TheAlgorithms/Java@fdfb9a395b (2026-08-13). Data as JSON: /api/errors/0e0a3656f93342fe. Report an issue: GitHub.