1. Introduction
When programming in Java, List is one of the most frequently used and important data structures. Using a List allows you to store multiple items in order and easily perform operations such as adding, removing, and searching elements as needed.
However, to use Lists effectively, it’s essential to fully understand the initialization methods. Incorrect initialization can cause unexpected errors or bugs and significantly impact readability and maintainability.
In this article, we focus on the topic of “Java List initialization” and explain everything from beginner-friendly basic initialization methods to practical techniques and common pitfalls. We also cover differences between Java versions and best practices based on real-world coding scenarios.
Whether you are just starting to learn Java or already using Lists regularly, this is a great opportunity to review and organize the different initialization patterns.
An FAQ section is provided at the end to help resolve common questions and issues.
2. Basic List Initialization Methods
When starting to use Lists in Java, the first step is to create an “empty List,” meaning initializing the List. Here, we explain the basic initialization methods using the most common implementation, ArrayList.
2.1 Creating an Empty List with new ArrayList<>()
The most commonly used initialization is with new ArrayList<>(), written as follows:
List<String> list = new ArrayList<>();This creates an empty List with no elements.
Key Points:
Listis an interface, so you instantiate a concrete class such asArrayListorLinkedList.- It is generally recommended to declare the variable as
Listfor flexibility.
2.2 Initializing with a Specified Initial Capacity
If you expect to store a large amount of data or already know the number of elements, specifying the initial capacity improves efficiency.
Example:
List<Integer> numbers = new ArrayList<>(100);This reserves space for 100 elements internally, reducing resizing costs when adding items and improving performance.
2.3 Initializing a LinkedList
You can also use LinkedList depending on your needs. Usage is nearly the same:
List<String> linkedList = new LinkedList<>();LinkedList is especially effective in situations where elements are frequently added or removed.
Java makes it easy to initialize empty Lists using new ArrayList<>() or new LinkedList<>().
3. Creating Lists with Initial Values
In many cases, you may want to create a List that already contains initial values. Below are the most common initialization patterns and their characteristics.
3.1 Using Arrays.asList()
One of the most frequently used methods in Java is Arrays.asList().
Example:
List<String> list = Arrays.asList("A", "B", "C");This creates a List with initial values.
Important Notes:
- The returned List is fixed-size and cannot change its length. Calling
add()orremove()will causeUnsupportedOperationException. - Replacing elements (with
set()) is allowed.
3.2 Using List.of() (Java 9+)
From Java 9 onward, List.of() allows easy creation of immutable Lists:
List<String> list = List.of("A", "B", "C");Characteristics:
- Fully immutable List—
add(),set(), andremove()are all prohibited. - Highly readable and ideal for constant values.
3.3 Creating a Mutable List from Arrays.asList()
If you want a List with initial values but also want to modify it later, this method is useful:
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));This creates a mutable List.
add()andremove()work normally.
3.4 Double-Brace Initialization
A more advanced technique that uses an anonymous class:
List<String> list = new ArrayList<>() {{
add("A");
add("B");
add("C");
}};Characteristics & Warnings:
- Creates compact code but introduces an anonymous class, causing extra overhead and possible memory leaks.
- Use it only for quick demos or test code; not recommended for production.
This shows that Java provides various ways to create Lists with initial values depending on your needs.
5. Comparison and Selection Criteria
Java offers a variety of List initialization methods, and the best choice depends on the use case. This section summarizes each method and explains when to choose which.
5.1 Mutable vs Immutable Lists
- Mutable Lists
- Elements can be added, removed, or modified.
- Examples:
new ArrayList<>(),new ArrayList<>(Arrays.asList(...)) - Best for dynamic operations or adding items in loops.
- Immutable Lists
- No additions, deletions, or modifications.
- Examples:
List.of(...),Collections.singletonList(...),Collections.nCopies(...) - Ideal for constants or safe value passing.
5.2 Comparison Table of Common Methods
| Method | Mutability | Java Version | Characteristics / Use Cases |
|---|---|---|---|
new ArrayList<>() | Mutable | All Versions | Empty List; add elements freely |
Arrays.asList(...) | Fixed Size | All Versions | Has initial values but size cannot change |
new ArrayList<>(Arrays.asList(...)) | Mutable | All Versions | Initial values + fully mutable; widely used |
List.of(...) | Immutable | Java 9+ | Clean immutable List; no modifications allowed |
Collections.singletonList(...) | Immutable | All Versions | Immutable List with a single value |
Collections.nCopies(n, obj) | Immutable | All Versions | Initialize with n identical values; useful for testing |
Stream.generate(...).limit(n) | Mutable | Java 8+ | Flexible pattern generation; good for random or sequential data |
5.3 Recommended Initialization Patterns by Use Case
- When you just need an empty List
new ArrayList<>()- When you need initial values and want to modify later
new ArrayList<>(Arrays.asList(...))- When using it as a constant with no modification
List.of(...)(Java 9+)Collections.singletonList(...)- When you want a fixed number of identical values
Collections.nCopies(n, value)- When values need to be generated dynamically
Stream.generate(...).limit(n).collect(Collectors.toList())

5.4 Important Notes
- Attempting to modify immutable or fixed-size Lists will result in exceptions.
- Choose the method that best fits your required mutability and Java version.
Choosing the right initialization method prevents unintended bugs and improves readability and safety.
6. Common Errors and How to Fix Them
Certain errors frequently occur when initializing or using Lists in Java. Here are common examples and their solutions.
6.1 UnsupportedOperationException
Common scenarios:
- Calling
add()orremove()on a List created viaArrays.asList(...) - Modifying a List created via
List.of(...),Collections.singletonList(...), orCollections.nCopies(...)
Example:
List<String> list = Arrays.asList("A", "B", "C");
list.add("D"); // Throws UnsupportedOperationExceptionCause:
- These methods create Lists that cannot change size or are fully immutable.
Solution:
- Wrap with a mutable List:
new ArrayList<>(Arrays.asList(...))
6.2 NullPointerException
Common scenario:
- Accessing a List that was never initialized
Example:
List<String> list = null;
list.add("A"); // NullPointerExceptionCause:
- A method is called on a
nullreference.
Solution:
- Always initialize before using:
List<String> list = new ArrayList<>();
6.3 Type-Related Issues
- Creating a List without generics increases the risk of runtime type errors.
Example:
List list = Arrays.asList("A", "B", "C");
Integer i = (Integer) list.get(0); // ClassCastExceptionSolution:
- Always use generics whenever possible.
Understanding these common errors will help you avoid issues when initializing or using Lists.
7. Summary
This article explained various List initialization methods in Java and how to choose the appropriate one.
We covered:
- Basic empty List creation using
new ArrayList<>()andnew LinkedList<>() - Lists with initial values using
Arrays.asList(),List.of(), andnew ArrayList<>(Arrays.asList(...)) - Special initialization patterns such as
Collections.singletonList(),Collections.nCopies(), andStream.generate() - Key differences between mutable and immutable Lists
- Common pitfalls and error handling
Although List initialization seems simple, understanding these variations and selecting the right method is crucial for safe and efficient coding.
8. FAQ (Frequently Asked Questions)
Q1: Can I add elements to a List created with Arrays.asList()?
A1: No. Arrays.asList() returns a fixed-size List. Calling add() or remove() will throw UnsupportedOperationException. Use new ArrayList<>(Arrays.asList(...)) for a mutable List.
Q2: What is the difference between List.of() and Arrays.asList()?
List.of()(Java 9+) → fully immutable; evenset()is not allowed.Arrays.asList()→ fixed-size butset()is allowed.
Q3: Should I use Double-Brace Initialization?
A3: It’s not recommended because it creates an anonymous class and may cause memory leaks. Use standard initialization instead.
Q4: What are the benefits of specifying an initial capacity?
A4: It reduces internal resizing when adding many elements, improving performance.
Q5: Should I always use generics when initializing Lists?
A5: Absolutely. Using generics improves type safety and prevents runtime errors.
Q6: What happens if I use a List without initializing it?
A6: Calling any method on it will cause a NullPointerException. Always initialize first.
Q7: Are there version differences in List initialization?
A7: Yes. List.of() is only available in Java 9 and later.

