Definition
This combines range generation with a predicate filter on a primitive int stream.
- IntStream.range(1, 11) – an exclusive range that emits
1, 2, ..., 10, stopping before11. - filter(IntPredicate) – keeps only the elements for which the predicate returns true, here the even numbers.
- n % 2 == 0 – the modulo test that is true for even numbers and false for odd numbers.
- Lazy pipeline –
filterdoes no work until a terminal operation such asforEachortoArrayruns. - No boxing –
IntStreamoperates on primitive ints, so there is noIntegerwrapper overhead.
At the National Bank of India, Rajesh lines up account tokens numbered one through ten on the counter. Because the range is exclusive, he asks for tokens up to but not including eleven, which gives him exactly ten tokens. Priya then says she only wants the even-numbered tokens for a special scheme. Rajesh runs his hand down the line and keeps only tokens two, four, six, eight, and ten, letting the odd ones fall away. The filter is that quick pass that keeps only what matches the rule.
Understanding the Concepts
How do you generate numbers 1 to 10 with IntStream.range?
IntStream.range(start, end) emits every integer from start up to but not including end. To get 1 through 10 you pass 1 and 11, because the upper bound is excluded.
package com.bank.demo;
import java.util.stream.IntStream;
public class RangeDemo {
public static void main(String[] args) {
IntStream.range(1, 11)
.forEach(System.out::println);
}
}
1
2
3
4
5
6
7
8
9
10
How do you filter the even numbers?
Add filter with the predicate n % 2 == 0. The filter keeps only elements for which the predicate is true.
package com.bank.demo;
import java.util.stream.IntStream;
public class FilterEven {
public static void main(String[] args) {
IntStream.range(1, 11)
.filter(n -> n % 2 == 0)
.forEach(System.out::println);
}
}
2
4
6
8
10
How do you collect the result into a list or array?
IntStream has toArray for a primitive array, and boxed to turn it into a Stream you can collect into a List.
package com.bank.demo;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class CollectResult {
public static void main(String[] args) {
int[] arr = IntStream.range(1, 11)
.filter(n -> n % 2 == 0)
.toArray();
System.out.println("array = " + Arrays.toString(arr));
List<Integer> list = IntStream.range(1, 11)
.filter(n -> n % 2 == 0)
.boxed()
.collect(Collectors.toList());
System.out.println("list = " + list);
}
}
array = [2, 4, 6, 8, 10]
list = [2, 4, 6, 8, 10]
Why is the upper bound 11 and not 10?
range is exclusive, so range(1, 10) would stop at 9 and miss 10. To include 10 you either pass 11 to range or use rangeClosed(1, 10).
| Expression | Produces | Includes 10 |
|------------|----------|-------------|
| range(1, 10) | 1 to 9 | no |
| range(1, 11) | 1 to 10 | yes |
| rangeClosed(1, 10) | 1 to 10 | yes |
package com.bank.demo;
import java.util.Arrays;
import java.util.stream.IntStream;
public class BoundProof {
public static void main(String[] args) {
System.out.println(Arrays.toString(IntStream.range(1, 10).toArray()));
System.out.println(Arrays.toString(IntStream.range(1, 11).toArray()));
System.out.println(Arrays.toString(IntStream.rangeClosed(1, 10).toArray()));
}
}
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
What are common mistakes?
The two frequent errors are an off-by-one on the bound and an inverted even test.
// WRONG: range(1, 10) misses 10; even filter then yields 2,4,6,8 (no 10)
IntStream.range(1, 10)
.filter(n -> n % 2 == 0)
.forEach(System.out::println); // 2 4 6 8
// WRONG: n % 2 == 1 is a trap for negative numbers and keeps odds, not evens
IntStream.range(1, 11)
.filter(n -> n % 2 == 1)
.forEach(System.out::println); // odd numbers
// CORRECT: range(1, 11) includes 10, and n % 2 == 0 selects evens safely
IntStream.range(1, 11)
.filter(n -> n % 2 == 0)
.forEach(System.out::println); // 2 4 6 8 10
Prefer n % 2 == 0 for even because n % 2 == 1 fails for negative odd numbers, where the result is -1.
How does filter behave with negative numbers?
For a negative odd number, n % 2 is -1 in Java, not 1. So n % 2 == 1 would wrongly reject -3. The safe even test n % 2 == 0 works for all signs.
package com.bank.demo;
import java.util.Arrays;
import java.util.stream.IntStream;
public class NegativeMod {
public static void main(String[] args) {
int[] evens = IntStream.rangeClosed(-4, 4)
.filter(n -> n % 2 == 0)
.toArray();
System.out.println(Arrays.toString(evens));
}
}
[-4, -2, 0, 2, 4]
Is filter lazy, and when does it run?
filter is a lazy intermediate operation. It does nothing until a terminal operation requests elements, at which point each value flows through the pipeline one at a time.
package com.bank.demo;
import java.util.stream.IntStream;
public class LazyFilter {
public static void main(String[] args) {
IntStream.range(1, 11)
.filter(n -> {
System.out.println("testing " + n);
return n % 2 == 0;
})
.limit(2) // only need the first 2 evens
.forEach(n -> System.out.println("kept " + n));
}
}
testing 1
testing 2
kept 2
testing 3
testing 4
kept 4
Because of laziness and limit(2), the pipeline stops after finding two evens rather than testing all ten numbers.
How is this applied in a banking context?
Suppose the bank issues account numbers 1 to 10 and wants only the even-numbered accounts for an even-day statement run. The same pipeline builds the list of account codes.
package com.bank.account;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class EvenAccounts {
public static void main(String[] args) {
List<String> evenAccounts = IntStream.range(1, 11)
.filter(n -> n % 2 == 0)
.mapToObj(n -> String.format("ACC-%03d", n))
.collect(Collectors.toList());
System.out.println(evenAccounts);
}
}
[ACC-002, ACC-004, ACC-006, ACC-008, ACC-010]
How does IntStream filtering compare to Stream?
IntStream filters primitive ints with no boxing, while a Stream boxes each value into an Integer. For numeric work the IntStream version is faster and clearer.
| Aspect | IntStream | Stream
|--------|-----------|------------------|
| Element type | primitive int | boxed Integer |
| Boxing overhead | none | one object per element |
| Predicate type | IntPredicate | Predicate |
| Numeric terminals | sum, average, max | needs mapToInt first |
package com.bank.demo;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class IntVsBoxed {
public static void main(String[] args) {
// Primitive, no boxing
int sumPrimitive = IntStream.range(1, 11)
.filter(n -> n % 2 == 0)
.sum();
// Boxed Integer stream, autoboxing on each element
int sumBoxed = Stream.iterate(1, n -> n + 1)
.limit(10)
.filter(n -> n % 2 == 0)
.mapToInt(Integer::intValue)
.sum();
System.out.println("primitive sum = " + sumPrimitive);
System.out.println("boxed sum = " + sumBoxed);
}
}
primitive sum = 30
boxed sum = 30
What are the edge cases?
An empty range produces no elements, and a range where start >= end is also empty and never runs the filter.
package com.bank.demo;
import java.util.stream.IntStream;
public class EmptyRange {
public static void main(String[] args) {
long count = IntStream.range(5, 5) // start == end, empty
.filter(n -> n % 2 == 0)
.count();
System.out.println("empty range count = " + count);
}
}
empty range count = 0
What are common interview follow-up questions?
Interviewers ask why the end is 11 not 10, how range differs from rangeClosed, whether filter is lazy, why n % 2 == 0 is safer than n % 2 == 1, and how IntStream avoids boxing. A tight answer: range is exclusive so 11 reaches 10, filter is a lazy predicate operation, n % 2 == 0 is sign-safe, and IntStream keeps everything primitive.
Visual Overview
IntStream.range(1, 11) // exclusive upper bound 1 2 3 4 5 6 7 8 9 10 (11 excluded) │ │ filter(n -> n % 2 == 0) ▼ ┌───────────────────────────────┐ │ keep even, drop odd │ │ 1✗ 2✓ 3✗ 4✓ 5✗ 6✓ 7✗ 8✓ 9✗ 10✓│ └───────────────────────────────┘ │ ▼ 2 4 6 8 10
Why end = 11
range(1, 10) -> 1 .. 9 (misses 10)
range(1, 11) -> 1 .. 10 (correct)
rangeClosed(1,10) -> 1 .. 10 (correct, inclusive form)
Lazy pipeline (pull model)
forEach / toArray ── pulls ──► filter ── pulls ──► range
▲ │ │
└──────── even value ─────────┘◄─── each int ───────┘
Nothing runs until the terminal operation pulls.
Key Takeaway
At the National Bank of India, Rajesh lines up account tokens numbered one through ten. Because IntStream.range uses an exclusive upper bound, he writes range(1, 11) so the stream stops just before eleven and gives him exactly ten numbers. If he had written range(1, 10) he would have lost the number ten, which is the single most common off-by-one mistake with ranges.
Priya then wants only the even tokens, so Rajesh adds filter(n -> n % 2 == 0). The filter is a quick pass that keeps the values matching the rule and lets the rest fall away, leaving two, four, six, eight, and ten. He prefers the == 0 test over == 1 because in Java a negative odd number gives -1 for n % 2, so the == 0 form stays correct for every sign.
The whole pipeline is lazy. filter does no work on its own; it waits until a terminal operation such as forEach, toArray, or boxed().collect pulls values through. That laziness is what lets a limit further down stop the work early after enough matches are found.
Because this is an IntStream, every value stays a primitive int with no boxing, which keeps numeric filtering fast and gives direct access to sum, average, and max. The same shape scales straight into banking work, like selecting even-numbered accounts for a statement run.
Remember one sentence: range is exclusive so use 11 to reach 10, then filter with n % 2 == 0 to keep the even numbers.
---