Back to Stream Creation & Utilities
Q10Question 10 of 18

Use IntStream.range(1, 11) to generate numbers 1-10, then filter even numbers

Key Concepts
  • IntStream.range(1, 11) produces 1 through 10 because the upper bound 11 is exclusive
  • filter(n -> n % 2 == 0) keeps only the even numbers 2, 4, 6, 8, 10
  • range is exclusive, so to reach 10 you pass 11 as the end, or use rangeClosed(1, 10)
  • filter is a lazy intermediate operation that runs only when a terminal operation pulls values
  • IntStream avoids boxing, so numeric filtering is more efficient than Stream<Integer>
  • The modulo test n % 2 == 0 is the standard even check, and n % 2 != 0 keeps odd numbers
  • A terminal operation like forEach, boxed().collect, or toArray materializes the filtered result

Definition

IntStream.range(1, 11) yields 1 to 10 because the end is exclusive, and filter(n -> n % 2 == 0) keeps the even ones, producing 2, 4, 6, 8, 10.

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 before 11.
  • 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 – filter does no work until a terminal operation such as forEach or toArray runs.
  • No boxing – IntStream operates on primitive ints, so there is no Integer wrapper 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.

JAVA
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);
    }
}
TEXT
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.

JAVA
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);
    }
}
TEXT
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.

JAVA
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);
    }
}
TEXT
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 |

JAVA
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()));
    }
}
TEXT
[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.

JAVA
// 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
JAVA
// 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.

JAVA
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));
    }
}
TEXT
[-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.

JAVA
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));
    }
}
TEXT
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.

JAVA
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);
    }
}
TEXT
[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 |

JAVA
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);
    }
}
TEXT
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.

JAVA
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);
    }
}
TEXT
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

DIAGRAM
  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
TEXT
  Why end = 11

  range(1, 10)      ->  1 .. 9    (misses 10)
  range(1, 11)      ->  1 .. 10   (correct)
  rangeClosed(1,10) ->  1 .. 10   (correct, inclusive form)
DIAGRAM
  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.

---

Share
Use ← → arrow keys to navigate