Primitive Streams

Basic Java
≈ 2 min read

Numeric primitives have dedicated streams

A regular Stream<Integer> works with wrapper objects. For common computations over primitive numbers, Java provides IntStream, LongStream, and DoubleStream. They let you work with int, long, and double without constant boxing and provide convenient numeric operations.

range and rangeClosed create ranges

int sum = IntStream.rangeClosed(1, 5)
        .sum();

rangeClosed(1, 5) contains the numbers from 1 through 5 inclusive, so the sum is 15. range(1, 5) would exclude the upper bound and create the sequence 1, 2, 3, 4.

Moving from objects to primitives

A regular stream can be converted to a primitive stream with mapToInt, mapToLong, or mapToDouble.

double average = List.of("Java", "Spring", "SQL").stream()
        .mapToInt(String::length)
        .average()
        .orElse(0.0);

After mapToInt, the result is an IntStream, so sum(), average(), min(), and max() are available without a manual reduce.

Returning to an object stream

If object-based operations are needed afterward, a primitive stream can be converted back with boxed().

List<Integer> values = IntStream.range(1, 4)
        .boxed()
        .toList();

The result is the list [1, 2, 3]. Moving between object and primitive streams is normal, but it is better not to switch back and forth without a reason.

Choose a primitive stream when the data is genuinely numeric. The code usually becomes more direct: instead of Stream<Integer> and a manual reduction, specialized numeric operations can be used immediately.