Java List.of(...) Use Cases
List.of(...) is a compact way to create a small immutable list in Java. It is great for constants, examples, test inputs, and quick return values, but it has a few edges worth remembering.
Version Support
List.of(...) was added in Java 9.
List<Integer> numbers = List.of(1, 2, 3);
Stream.toList() was added later in Java 16.
List<Integer> copy = numbers.stream().toList();
If you are on Java 8, use Arrays.asList(...), Collections.unmodifiableList(...), or an ArrayList depending on whether you need mutability.
Basic Use
List<Integer> a = List.of(1, 2);
This creates an immutable list containing 1 and 2.
You cannot add, remove, or replace elements:
a.add(3); // throws UnsupportedOperationException
Use this when the list is meant to be a fixed value.
List.of(a) Creates A Nested List
This line does not copy the elements from a:
List<Integer> a = List.of(1, 2);
var c = List.of(a);
The type of c is:
List<List<Integer>>
The value is:
[[1, 2]]
That means List.of(a) creates a list with one element, and that one element is the list a.
Use this when you intentionally want a list of lists.
Two Lists Inside One Outer List
If you write:
List<Integer> a = List.of(1, 2);
List<Integer> b = List.of(3, 4);
var d = List.of(a.stream().toList(), b.stream().toList());
The type of d is:
List<List<Integer>>
The value is:
[[1, 2], [3, 4]]
This is useful when you want to preserve the two lists as separate groups.
For Java 10 to Java 15, replace stream().toList() with:
List.copyOf(a)
Example:
var d = List.of(List.copyOf(a), List.copyOf(b));
For Java 9 specifically, use:
var d = List.of(
Collections.unmodifiableList(new ArrayList<>(a)),
Collections.unmodifiableList(new ArrayList<>(b))
);
Combining Two Lists Into One List
If the goal is one flat list, do not use List.of(a, b). That gives a nested list:
var nested = List.of(a, b); // [[1, 2], [3, 4]]
Instead, create a mutable copy and add the other list:
List<Integer> e = List.of(3, 4);
List<Integer> f = new ArrayList<>(e);
f.addAll(a);
Now f is:
[3, 4, 1, 2]
If you want a first:
List<Integer> f = new ArrayList<>(a);
f.addAll(e);
Result:
[1, 2, 3, 4]
Stream-Based Merge
In Java 16+, you can merge lists with streams:
List<Integer> merged = Stream.concat(a.stream(), b.stream()).toList();
This returns an unmodifiable list.
Remember the imports:
import java.util.stream.Stream;
If you need a mutable list:
List<Integer> merged = Stream.concat(a.stream(), b.stream())
.collect(Collectors.toCollection(ArrayList::new));
Imports:
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Nulls Are Not Allowed
List.of(...) rejects null values:
List.of(1, null); // throws NullPointerException
This is different from new ArrayList<>(), which can hold null.
Quick Decision Table
| Need | Use |
|---|---|
| Small immutable list | List.of(1, 2, 3) |
| List containing another list | List.of(a) |
| Two lists as two groups | List.of(a, b) |
| One combined mutable list | new ArrayList<>(a); addAll(b); |
| One combined immutable list in Java 16+ | Stream.concat(a.stream(), b.stream()).toList() |
| Defensive immutable copy in Java 10+ | List.copyOf(existingList) |
Takeaways
List.of(...)is available from Java 9.Stream.toList()is available from Java 16.List.of(a)creates a nested list, not a copy ofa's elements.- Use
new ArrayList<>(a)plusaddAll(b)when you want one mutable combined list. - Use
List.of(...)for fixed values, not lists you plan to edit.