ZetCode

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 StreamBoxed EquivalentBoxing MethodUnboxing Method
IntStreamStream<Integer>boxed()mapToInt(Integer::intValue)
LongStreamStream<Long>boxed()mapToLong(Long::longValue)
DoubleStreamStream<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>.

Main.java
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.

Main.java
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.

Main.java
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.

Main.java
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.

Main.java
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.

Main.java
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.

Main.java
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.

Main.java
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

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Java tutorials.