Create a Java List with a Single Element (List.of, singletonList)

Create a Java list with a single element using List.of(), Collections.singletonList(), Arrays.asList() or ArrayList. Mutability and null rules compared.

Decision tree for a single-element list in Java. If the list must grow, use new ArrayList with List.of. Otherwise, if the element can be null, use Collections.singletonList, else use List.of

The shortest way to create a Java list with a single element is List.of(“apple”), which returns an unmodifiable list, and new ArrayList<>(List.of(“apple”)) gives a list that can grow later. Older code uses Collections.singletonList() and Arrays.asList(), which also return one-element lists but behave differently when we change them or pass null.

We need a one-element list when an API asks for a List and we have only one value, for example a single recipient for an email service, one role for a test user, or one media type for an HTTP header.

The following example creates the same one-element list in five ways.

List<String> viaListOf = List.of("apple");                          // [apple]
List<String> viaSingleton = Collections.singletonList("apple");     // [apple]
List<String> viaAsList = Arrays.asList("apple");                    // [apple]
List<String> growable = new ArrayList<>(List.of("apple"));          // [apple]
List<String> viaStream = Stream.of("apple").toList();               // [apple]

All five lists print the same and are equal to each other, but only growable accepts a second element. We compare what each list allows and which one to choose, and finish with one-element sets and maps.

1. Choosing a Java List With a Single Element

The five lists differ in three ways, namely whether we can add or remove elements, whether we can replace the element with set(), and whether the element may be null. An operation that the list does not allow throws an UnsupportedOperationException.

Methodadd() / remove()set(0, x)null elementSince
List.of(e)ThrowsThrowsNullPointerExceptionJava 9
Collections.singletonList(e)ThrowsThrowsAllowedJava 1.3
Arrays.asList(e)ThrowsAllowedAllowedJava 1.2
new ArrayList<>(List.of(e))AllowedAllowedAllowed with add(null)Java 9
Stream.of(e).toList()ThrowsThrowsAllowedJava 16

Most code needs either a read-only list or a growable one, and the decision comes down to two questions.

Decision tree for a single-element list in Java. If the list must grow, use new ArrayList with List.of. Otherwise, if the element can be null, use Collections.singletonList, else use List.of
Pick List.of() by default, Collections.singletonList() when the element may be null, and an ArrayList copy when the list must grow

2. List.of() for an Unmodifiable List

Since Java 9, the factory method List.of(e) is the shortest way to get a read-only list. The result is unmodifiable, so add(), remove(), set() and sort() throw an UnsupportedOperationException.

List<String> fruits = List.of("apple");
String first = fruits.get(0);                       // "apple"
boolean added = fruits.add("banana");              // UnsupportedOperationException

The method List.of() rejects null, and even contains(null) on its result throws a NullPointerException. That catches a missing value early, but it surprises code that checks list.contains(null) on lists from many sources.

String missing = null;
List<String> nullList = List.of(missing);                        // NullPointerException
boolean hasNull = List.of("apple").contains(null);               // NullPointerException

The immutable collections factory methods article covers List.of() with more elements, and initializing a list in one line compares it with the other one-line options.

3. Collections.singletonList() and the Null Case

The method Collections.singletonList() has existed since Java 1.3 and returns an immutable list that holds a single element. It behaves like List.of() for changes, with one practical difference. It accepts null.

List<String> single = Collections.singletonList("apple");     // [apple]
List<String> withNull = Collections.singletonList(null);       // [null]
boolean hasNull = single.contains(null);                       // false
String replaced = single.set(0, "banana");                     // UnsupportedOperationException

A Spring app that calls a REST API sets one accepted media type on the request headers. The method HttpHeaders.setAccept() takes a List<MediaType>, so a one-element list is the natural argument, and List.of() works the same way here.

HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
List<MediaType> accepted = headers.getAccept();               // [application/json]

We pick Collections.singletonList() over List.of() when the value may be null on purpose, or in code that must still run on Java 8. Otherwise, List.of() is the better default because it fails fast on a missing value.

4. Arrays.asList() Returns a Fixed-Size List

The method Arrays.asList() wraps its arguments in a list backed by an array. The size is fixed, so add() and remove() throw, but set() works because it only replaces an array slot.

List<String> fixed = Arrays.asList("apple");
String old = fixed.set(0, "banana");               // "apple"
String now = fixed.get(0);                         // "banana"
boolean grown = fixed.add("cherry");               // UnsupportedOperationException

We rarely want this middle ground for a single element. The Arrays.asList() vs new ArrayList() article explains the backing array in detail.

5. A Mutable List With One Element

A shopping cart in a food delivery app starts with the dish the user tapped, and the user adds more dishes later. The list must grow, so we copy the first element into an ArrayList.

List<String> cart = new ArrayList<>(List.of("pizza"));
cart.add("salad");                                  // cart = [pizza, salad]
List<String> cart2 = new ArrayList<>();
cart2.add("pizza");                                 // cart2 = [pizza]

For a null first element, we use the second form, because List.of(null) throws before the copy happens. We avoid Stream.of(e).collect(Collectors.toList()) for a mutable list, since Collectors.toList() gives no guarantee about the list type or its mutability. It returns an ArrayList today, but Collectors.toCollection(ArrayList::new) states that intent in code.

List<String> collected = Stream.of("pizza").collect(Collectors.toCollection(ArrayList::new));    // [pizza]
List<String> readOnly = Stream.of("pizza").toList();                                            // [pizza]

6. Single-Element Sets and Maps

The same choice exists for sets and maps. The factory methods from Java 9 reject null, while the older Collections methods accept it, and all of them are immutable.

Set<String> oneTag = Set.of("vegan");                                    // [vegan]
Set<String> oneTagOld = Collections.singleton("vegan");                    // [vegan]
Map<String, Integer> oneStock = Map.of("apple", 5);                        // {apple=5}
Map<String, Integer> oneStockOld = Collections.singletonMap("apple", 5);   // {apple=5}

When an API needs a list of the same value repeated, Collections.nCopies(n, e) returns an immutable list of n references to e without storing n elements.

List<String> placeholders = Collections.nCopies(3, "?");           // [?, ?, ?]
String sql = String.join(", ", placeholders);                     // "?, ?, ?"

7. Single-Element List FAQs

The one-element lists look alike when printed, but they react differently to changes and to calls from several threads.

7.1. What is the difference between Collections.singletonList() and List.of()?

Both return a one-element list that throws on any change, and the two lists are equal(). The method Collections.singletonList() accepts null and works on Java 8, whereas List.of() throws a NullPointerException for null and needs Java 9.

boolean same = List.of("apple").equals(Collections.singletonList("apple"));    // true

7.2. Why does add() on a singletonList throw UnsupportedOperationException?

The list is immutable by design, and add() is an optional operation that it does not support. We copy it into an ArrayList first, as in section 5. The UnsupportedOperationException article lists the other lists that behave this way.

7.3. Is Collections.singletonList() thread-safe?

Yes, for reading. The list itself never changes, so any number of threads can read it without locks. The element inside is not protected, so a mutable element still needs its own synchronization.

7.4. Can we sort a single-element list?

Sorting a list with one element never changes it, but the list types react differently. The list from List.of() throws UnsupportedOperationException on sort(), whereas Collections.singletonList() and an ArrayList accept the call.

8. Conclusion

For a read-only list with one element, List.of(e) is the default on Java 9 and later. We switch to Collections.singletonList(e) when the element may be null or the code runs on Java 8, and we wrap the value in new ArrayList<>() when the list must grow.

The method Arrays.asList() sits in between with a fixed size and a replaceable element, so we keep it for arrays rather than single values.

9. References

Happy Learning !!

Source Code on Github

Leave a Comment

Comments are closed.

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.