How to convert Java Stream to List

April 27, 2024 | No comments

Converting a Stream to a List is one of the most common stream operations. There are several ways to do it depending on your Java version and whether you need a mutable list.


Method 1: collect(Collectors.toList()) — Java 8+

The classic approach using the collect() terminal operation:

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
List<Integer> list = stream.collect(Collectors.toList());

System.out.println(list); // [1, 2, 3, 4, 5]

This returns a mutable ArrayList. You can add or remove elements from the result.


Method 2: Stream.toList() — Java 16+

Java 16 introduced a shorter, built-in method:

List<Integer> list = Stream.of(1, 2, 3, 4, 5).toList();
System.out.println(list); // [1, 2, 3, 4, 5]
Important: Stream.toList() returns an unmodifiable list. Trying to add or remove elements will throw UnsupportedOperationException. Use this when you don't need to mutate the result.

Method 3: collect(Collectors.toUnmodifiableList()) — Java 10+

If you want an unmodifiable list but are on Java 10–15:

List<Integer> list = Stream.of(1, 2, 3, 4, 5)
        .collect(Collectors.toUnmodifiableList());

Method 4: Collecting to a Specific List Type

If you need a specific List implementation (e.g., LinkedList):

import java.util.LinkedList;
import java.util.stream.Collectors;

List<Integer> linkedList = Stream.of(1, 2, 3, 4, 5)
        .collect(Collectors.toCollection(LinkedList::new));

Common Pattern: Filter, Transform, Collect

The real power shows when you chain operations before collecting:

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

List<String> names = Stream.of("alice", "bob", "charlie", "dave", "eve")
        .filter(name -> name.length() > 3)
        .map(String::toUpperCase)
        .collect(Collectors.toList());

System.out.println(names); // [ALICE, CHARLIE, DAVE]

Which Method to Use?

MethodJava VersionMutable?Notes
collect(Collectors.toList())8+YesMost common, returns ArrayList
Stream.toList()16+NoShortest syntax
collect(Collectors.toUnmodifiableList())10+NoExplicit about immutability
collect(Collectors.toCollection(...))8+YesWhen you need a specific type

For most cases on Java 16+, prefer Stream.toList() for its conciseness. On Java 8–15, use collect(Collectors.toList()).


Converting IntStream / LongStream to List

Primitive streams (IntStream, LongStream, DoubleStream) can't collect directly to List<Integer>. Use boxed() first to convert each primitive to its wrapper type:

// IntStream to List<Integer>
List<Integer> intList = IntStream.range(1, 6)
        .boxed()
        .collect(Collectors.toList());

System.out.println(intList); // [1, 2, 3, 4, 5]

// LongStream to List<Long>
List<Long> longList = LongStream.of(100L, 200L, 300L)
        .boxed()
        .collect(Collectors.toList());

// int[] array to List<Integer>
int[] arr = {10, 20, 30};
List<Integer> fromArray = Arrays.stream(arr)
        .boxed()
        .collect(Collectors.toList());

The boxed() call is required because List is a generic type and can't hold primitive int — only reference type Integer.


Collecting to Set and Map

The same pattern works for other collection types:

// Collect to a Set (deduplication)
Set<String> uniqueNames = Stream.of("alice", "bob", "alice", "charlie")
        .collect(Collectors.toSet());

// Collect to a Map (key = string, value = its length)
Map<String, Integer> nameLengths = Stream.of("alice", "bob", "charlie")
        .collect(Collectors.toMap(
            name -> name,           // key function
            String::length          // value function
        ));

Handling Null Elements

Both Collectors.toList() and Stream.toList() accept null elements in the stream. However, Stream.toList()'s unmodifiable list permits null values, while Collectors.toUnmodifiableList() throws a NullPointerException if the stream contains nulls:

Stream<String> withNull = Stream.of("a", null, "b");

// Works fine — ArrayList allows null
List<String> mutable = withNull.collect(Collectors.toList());

// Works fine — Stream.toList() allows null
Stream<String> withNull2 = Stream.of("a", null, "b");
List<String> immutable = withNull2.toList();

// Throws NullPointerException!
Stream<String> withNull3 = Stream.of("a", null, "b");
List<String> noNull = withNull3.collect(Collectors.toUnmodifiableList());

If your stream may contain nulls and you want an unmodifiable list, use Stream.toList() rather than Collectors.toUnmodifiableList().


Summary

collect(Collectors.toList()) is the standard way to convert a Stream to a List. On Java 16+, Stream.toList() is cleaner and should be your default when you don't need to mutate the result. For primitive streams (IntStream, etc.), call boxed() before collecting. Watch out for null handling differences between the unmodifiable collectors.

No comments :

Post a Comment

Please leave your message queries or suggetions.

Note: Only a member of this blog may post a comment.