Java IntStream rangeClosed: Inclusive Range Generation
java intstream rangeclosed: Learn how to use IntStream.rangeClosed in Java to generate inclusive integer ranges, with syntax, examples, and common mistakes to avoid.
java intstream rangeclosed requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.
When you need a stream of integers that includes both endpoints, IntStream.rangeClosed(int startInclusive, int endInclusive) is the method to use. It produces a sequential ordered stream from startInclusive to endInclusive inclusive, incrementing by 1. This is a common tool for loops, indexing, and generating test data. The method is part of the java.util.stream.IntStream interface, available since Java 8.
IntStream.rangeClosed Syntax and Basic Behavior
The signature is straightforward:
static IntStream rangeClosed(int startInclusive, int endInclusive)
It returns an IntStream containing the integers from startInclusive through endInclusive. For example:
IntStream.rangeClosed(1, 5) .forEach(System.out::println);
This prints 1 2 3 4 5. The stream is sequential and ordered, and each element is produced lazily when consumed by a terminal operation. The method does not allocate an array; it generates values on demand.
rangeClosed vs range: Inclusive vs Exclusive Endpoint
The sibling method IntStream.range(int startInclusive, int endExclusive) excludes the upper bound. The choice between them depends on whether you need the endpoint included.
| Method | Endpoint behavior | Example (1, 5) | Use case |
|---|---|---|---|
range | Exclusive | 1, 2, 3, 4 | Zero-based indexing, array length |
rangeClosed | Inclusive | 1, 2, 3, 4, 5 | Inclusive numeric ranges, loop counters with <= |
If you are iterating over an array of length n, range(0, n) is natural because valid indices are 0 to n-1. If you need to include the upper bound, such as a countdown from 10 to 0, rangeClosed(0, 10) is correct. Mixing these up is a frequent source of off-by-one errors.
Practical Usage Patterns for rangeClosed
Beyond simple printing, rangeClosed is often used with other stream operations. For example, to sum a range:
int total = IntStream.rangeClosed(1, 100).sum();
To map each integer to a value, like squares:
List<Integer> squares = IntStream.rangeClosed(1, 10) .map(n -> n * n) .boxed() .collect(Collectors.toList());
It also works well for generating indices for list access:
List<String> items = List.of("a", "b", "c"); IntStream.rangeClosed(0, items.size() - 1) .forEach(i -> System.out.println(i + ": " + items.get(i)));
Note that rangeClosed increments by exactly 1. There is no overload to specify a step size. For custom increments, use IntStream.iterate or a traditional for loop.
Performance Considerations: Lazy Evaluation and Overhead
IntStream.rangeClosed is lazy: no values are computed until a terminal operation is invoked. This means you can chain intermediate operations without materializing the entire range. For example, IntStream.rangeClosed(1, 1_000_000).filter(n -> n % 2 == 0).limit(10) only processes enough values to satisfy the limit.
However, streams introduce some overhead compared to a simple for loop. For tight, performance-critical loops over millions of elements, a traditional loop may be faster because it avoids stream abstraction and potential boxing when converting to Stream<Integer>. The difference is usually negligible for typical business logic, but if you are processing huge ranges in a hot path, consider measuring both approaches.
Memory usage is also constant: rangeClosed does not pre-allocate an array. This is a clear advantage over manually building a list of integers.
Common Mistakes and Edge Cases
One common mistake is assuming rangeClosed supports a step other than 1. It does not. If you need even numbers, you must use filter or iterate.
Another edge case is an empty range. If startInclusive is greater than endInclusive, the stream is empty. For example, IntStream.rangeClosed(5, 1) produces no elements. This is different from some other languages where a descending range might be generated. If you need descending order, you can use iterate or reverse the stream.
Overflow is also possible. If endInclusive is Integer.MAX_VALUE, the stream will attempt to produce values up to that bound, which is fine, but operations like sum() can overflow. Be mindful of the range size when performing arithmetic.
When to Use rangeClosed vs Other Range Alternatives
rangeClosed is ideal for fixed, inclusive integer ranges. But there are alternatives:
IntStream.rangewhen the endpoint is exclusive.IntStream.iteratefor custom steps or unbounded sequences.- A traditional
forloop when you need mutable state or a step that isn't 1.
For example, to iterate from 1 to 10 with a step of 2:
for (int i = 1; i <= 10; i += 2) { ... }
Or with iterate:
IntStream.iterate(1, i -> i <= 10, i -> i + 2) .forEach(...);
The iterate overload with a predicate is available since Java 9. If you are on Java 8, you need a different approach, such as IntStream.iterate(1, i -> i + 2).limit(5).
Compatibility and Version Notes
IntStream.rangeClosed has been available since Java 8 and remains unchanged in later versions. It is part of the standard Stream API, so no external dependencies are needed. The behavior is consistent across all Java implementations that support Java 8 or later. There are no known compatibility issues, but be aware that the iterate overload with a predicate was introduced in Java 9, so code using it will not compile on Java 8.
When using rangeClosed in a multi-threaded context, you can call .parallel() on the stream. The stream will split the range efficiently because the source is a range of integers. This is a safe way to parallelize independent operations over a numeric range.
For most use cases, IntStream.rangeClosed is a clean, expressive way to generate an inclusive range of integers. It integrates well with the rest of the Stream API and avoids manual index management. Just remember the inclusive endpoint, the fixed step of 1, and the empty range behavior when the start is greater than the end.