Why Stream.toList() Throws UnsupportedOperationException vs collect(Collectors.toList())

This article explains the key differences between Java's Stream toList() method introduced in JDK 16, which returns an unmodifiable list, and the traditional collect(Collectors.toList()) which yields a mutable ArrayList, illustrating behavior with code examples, performance considerations, and practical usage tips.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Why Stream.toList() Throws UnsupportedOperationException vs collect(Collectors.toList())

Background

In a development environment an UnsupportedOperationException appeared when a colleague used

stringList.stream().filter(number -> Long.parseLong(number) > 1).toList()

and then tried to add elements to the returned list, revealing misuse of an unmodifiable collection.

Difference between Stream.toList() and collect(Collectors.toList())

JDK version: 21

IDE: IDEA

Since Java 16 the Stream API provides a direct toList() terminal operation. The list returned by toList() is unmodifiable; any mutating call (e.g., add, remove) throws UnsupportedOperationException. The classic collect(Collectors.toList()) creates a mutable ArrayList.

/**
 * Accumulates the elements of this stream into a {@code List}. The elements
 * are in encounter order, if one exists. The returned List is unmodifiable;
 * calls to any mutator method will always cause {@code UnsupportedOperationException}.
 * @since 16
 */
@SuppressWarnings("unchecked")
default List<T> toList() {
    return (List<T>) Collections.unmodifiableList(new ArrayList<>(Arrays.asList(this.toArray())));
}

The implementation of toList() ultimately delegates to Collections.unmodifiableList, which wraps the supplied list in an unmodifiable view:

return (list instanceof RandomAccess)
        ? new UnmodifiableRandomAccessList<>(list)
        : new UnmodifiableList<>(list);
Diagram
Diagram

Although the list itself cannot be altered, the objects contained in it can still be mutated if they are mutable.

List<String> stringList = List.of("1", "2", "3");
List<String> largeNumberList = stringList.stream()
    .filter(number -> Long.parseLong(number) > 1)
    .toList(); // unmodifiable
List<String> largeNumberList2 = stringList.stream()
    .filter(number -> Long.parseLong(number) > 1)
    .collect(Collectors.toList()); // mutable

largeNumberList.add("4"); // throws UnsupportedOperationException
largeNumberList2.add("4"); // succeeds

User userZhang = new User("ZhangSan");
User userLi = new User("LiSi");
List<User> userList = List.of(userZhang, userLi);
List<User> filterList = userList.stream()
    .filter(user -> "LiSi".equals(user.name))
    .toList(); // unmodifiable list of mutable objects
User first = filterList.getFirst(); // Java 21
first.name = "WangWu"; // mutates the underlying object
filterList.forEach(u -> System.out.println(u.name));

How to use (ignoring performance)

Use Stream.toList() when you need an immutable list. If you prefer a mutable list and want to silence static‑analysis warnings, replace collect(Collectors.toList()) with collect(Collectors.toCollection(ArrayList::new)).

Source: juejin.cn/post/7325717778597904420
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaCollectionsStream APICollectorsJDK16Immutable List
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.