Java Stream boxed Method
last modified June 1, 2025
The boxed method in Java Streams is a crucial operation when
working with primitive streams. This tutorial explains its purpose, use cases,
and provides practical examples.
Stream.boxed is an intermediate operation that converts a primitive
stream (IntStream, LongStream, or DoubleStream)
into a Stream of corresponding
wrapper objects (Stream<Integer>, Stream<Long>, or
Stream<Double>). This operation is known as "boxing" -
converting primitive values to their object equivalents.
The boxed operation is particularly useful when you need to work with APIs that require object streams rather than primitive streams, or when you need to use operations that aren't available on primitive streams.
Primitive vs Object Streams
Java distinguishes between primitive streams (IntStream,
LongStream, DoubleStream) and object streams
(Stream<T>). Primitive streams are optimized for performance
and memory usage, but sometimes you need to convert them to object streams to
use certain APIs or operations. The boxed method bridges this gap
by converting primitive values to their corresponding wrapper objects.
| Primitive Stream | Boxed Equivalent | Boxing Method | Unboxing Method |
|---|---|---|---|
| IntStream | Stream<Integer> | boxed() | mapToInt(Integer::intValue) |
| LongStream | Stream<Long> | boxed() | mapToLong(Long::longValue) |
| DoubleStream | Stream<Double> | boxed() | mapToDouble(Double::doubleValue) |
The boxed method is used to convert primitive streams to their
object equivalents, allowing you to use standard Stream operations
that aren't available on primitive streams. Conversely, unboxing methods like
mapToInt, mapToLong, and mapToDouble
convert object streams back to primitive streams for performance-sensitive
operations.
Basic boxed Usage
This example demonstrates the most basic use of the boxed method to convert an
IntStream to a Stream<Integer>.
void main() {
IntStream.range(1, 5)
.boxed() // Convert IntStream to Stream<Integer>
.forEach(System.out::println);
}
Here we create an IntStream with values 1 through 4, then convert
it to a Stream<Integer> using boxed. This allows us to use
standard Stream operations that aren't available on primitive
streams.
$ java Main.java 1 2 3 4
Collecting Primitive Streams
One common use case for boxed is when you need to collect primitive
stream elements into collections that can't store primitive values.
void main() {
List<Integer> numbers = IntStream.of(10, 20, 30)
.boxed()
.toList();
System.out.println(numbers);
}
Since Collections can only hold objects, we need to box the primitive int values
before collecting them into a List. The boxed
operation performs this conversion automatically.
$ java Main.java [10, 20, 30]
Using with Stream Operations
Some Stream operations are only available on object streams. This example shows
using boxed to enable these operations.
void main() {
DoubleStream.of(1.1, 2.2, 3.3)
.boxed() // Convert to Stream<Double>
.sorted((a, b) - b.compareTo(a)) // Reverse sort
.forEach(System.out::println);
}
The sorted method with a custom comparator isn't available on
DoubleStream, so we first convert to
Stream<Double> using boxed. This gives us access
to all Stream operations.
$ java Main.java 3.3 2.2 1.1
Boxed for Grouping and Collecting
The boxed method is useful when you want to group or collect
primitive values using collectors that require objects, such as grouping numbers
by even/odd.
void main() {
Map<String, List<Integer>> grouped = IntStream.rangeClosed(1, 10)
.boxed()
.collect(Collectors.groupingBy(n -> n % 2 == 0 ? "Even" : "Odd"));
System.out.println(grouped);
}
This example groups numbers from 1 to 10 into even and odd categories using
Collectors.groupingBy. Since collectors work with objects,
boxed is necessary to convert the primitive stream.
Combining with Other Streams
When you need to combine primitive streams with object streams,
boxed becomes essential.
void main() {
Stream.concat(
IntStream.range(1, 4).boxed(),
Stream.of("a", "b", "c")
).forEach(System.out::println);
}
The Stream.concat method requires both parameters to be of the same
type (Stream<T>). We use boxed to convert the
IntStream to Stream<Integer> so it can be
concatenated with Stream<String>.
$ java Main.java 1 2 3 a b c
Performance Considerations
While boxed is convenient, it has performance implications due to
object creation. This example demonstrates the overhead.
void main() {
long start, end;
// Without boxing
start = System.nanoTime();
int sum1 = IntStream.range(0, 1_000_000).sum();
end = System.nanoTime();
System.out.println(sum1);
System.out.println("Primitive sum: " + (end - start) + " ns");
// With boxing
start = System.nanoTime();
int sum2 = IntStream.range(0, 1_000_000)
.boxed()
.reduce(0, Integer::sum);
end = System.nanoTime();
System.out.println(sum2);
System.out.println("Boxed sum: " + (end - start) + " ns");
}
The boxed version requires creating 1,000,000 Integer objects and
then converting them back to primitives for summing. The primitive version
operates directly on primitive values without this overhead.
$ java Main.java 1783293664 Primitive sum: 15442200 ns 1783293664 Boxed sum: 61258700 ns
Alternative to boxed
In some cases, mapToObj can be used as an alternative to
boxed, especially when you need to perform additional
transformations.
void main() {
IntStream.range(0, 5)
.mapToObj(i - "Item " + i) // Alternative to boxed
.forEach(System.out::println);
}
Here we use mapToObj to both convert the int values to objects and
transform them into strings. This is more efficient than using
followed by map when you need both operations.
$ java Main.java Item 0 Item 1 Item 2 Item 3 Item 4
Working with Optional
When dealing with Optional results from primitive streams,
boxed helps convert to Optional of the wrapper type.
void main() {
OptionalDouble avg = DoubleStream.of(1.5, 2.5, 3.5).average();
// Convert OptionalDouble to Optional<Double>
Optional<Double> boxedAvg = avg.stream().boxed().findFirst();
boxedAvg.ifPresent(d - System.out.println("Average: " + d));
}
Primitive stream terminal operations return Optional variants
(OptionalInt, OptionalLong,
OptionalDouble). The boxed
method helps convert these to regular Optional<T> when
needed.
$ java Main.java Average: 2.5
Source
Java IntStream.boxed Documentation
The boxed method is an essential tool when working with Java
Streams, particularly when you need to bridge between primitive and object
streams. While it introduces some overhead, it enables powerful stream
operations that wouldn't otherwise be possible with primitive streams.
Author
List all Java tutorials.