Java 8
IntStream
List Conversion
Programming
Coding Tutorial

How do I convert a Java 8 IntStream to a List?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

IntStream is a primitive stream, so it does not directly collect into a List<Integer> the way an object stream does. The standard Java 8 solution is to box the primitive int values into Integer objects and then collect the boxed stream into a list.

The Normal Java 8 Pattern

The usual approach is boxed() followed by collect(Collectors.toList()).

java
1import java.util.List;
2import java.util.stream.Collectors;
3import java.util.stream.IntStream;
4
5public class Main {
6    public static void main(String[] args) {
7        List<Integer> values = IntStream.range(1, 6)
8            .boxed()
9            .collect(Collectors.toList());
10
11        System.out.println(values);
12    }
13}

IntStream.range(1, 6) produces primitive values 1 through 5. boxed() converts each primitive int into an Integer, which makes the stream compatible with the usual object-based collectors.

Why Boxing Is Required

The Stream API has specialized primitive streams such as IntStream, LongStream, and DoubleStream to avoid boxing overhead during numeric operations. That is useful for performance, but it also means primitive streams do not expose the same collectors as Stream<Integer>.

So this works:

java
IntStream.range(1, 4).boxed().collect(Collectors.toList())

But this does not exist as a direct primitive-stream shortcut in Java 8:

java
// not valid Java 8 API
// IntStream.range(1, 4).collect(Collectors.toList())

The collector expects object elements, not primitives.

Creating a Specific List Type

Collectors.toList() usually returns a mutable list, but the exact implementation is not guaranteed. If you want a specific type such as ArrayList, provide the collection explicitly.

java
1import java.util.ArrayList;
2import java.util.List;
3import java.util.stream.Collectors;
4import java.util.stream.IntStream;
5
6public class Main {
7    public static void main(String[] args) {
8        List<Integer> values = IntStream.of(10, 20, 30)
9            .boxed()
10            .collect(Collectors.toCollection(ArrayList::new));
11
12        values.add(40);
13        System.out.println(values);
14    }
15}

This is helpful when later code depends on mutability or on a specific list implementation.

Remember That Streams Are Single-Use

A stream can be consumed only once. If you collect an IntStream into a list, you cannot reuse that same stream object afterward.

java
1IntStream stream = IntStream.rangeClosed(1, 3);
2List<Integer> values = stream.boxed().collect(Collectors.toList());
3System.out.println(values);
4
5// stream.count(); // would fail because the stream is already consumed

If you need the data again, create a new stream source.

When a List Is Not Actually Necessary

Sometimes the real goal is just to pass numbers onward, not to store them as boxed objects. In those cases, staying with primitive arrays or continuing the stream pipeline may be more efficient.

java
int[] values = IntStream.rangeClosed(1, 5).toArray();

A List<Integer> is convenient, but it introduces boxing and object allocation. That is fine for most application code, but worth remembering in performance-sensitive paths.

Common Pitfalls

The most common mistake is trying to call collect(Collectors.toList()) directly on IntStream without boxing first. In Java 8, that is not how the API is designed.

Another mistake is forgetting that boxing changes primitives into objects. For most cases this is fine, but it does have a cost if you are processing very large volumes of numbers.

Developers also sometimes assume Collectors.toList() guarantees an ArrayList. It does not. If the concrete list type matters, use toCollection.

Finally, remember that a stream is single-use. Once you collect it, the original stream cannot be traversed again.

Summary

  • In Java 8, convert IntStream to List<Integer> with boxed().collect(Collectors.toList()).
  • Boxing is required because IntStream is a primitive stream, not an object stream.
  • Use Collectors.toCollection(ArrayList::new) if you need a specific mutable list type.
  • Streams are single-use and cannot be consumed twice.
  • If you only need numeric storage, an int[] may be simpler and more efficient.

Course illustration
Course illustration

All Rights Reserved.