Question
I want to create a list of string values for testing purposes in Java. My original code was:
ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");
I then refactored it to:
ArrayList<String> places = new ArrayList<String>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata")
);
Is there a better or more idiomatic way to initialize an ArrayList in one line?
Short Answer
By the end of this page, you will understand several common ways to initialize lists in Java, especially ArrayList in a single line. You will learn when to use Arrays.asList(...), when to wrap it in new ArrayList<>(...), how modern Java uses List.of(...), and how mutability affects which approach is best.
Concept
In Java, list initialization is really about two separate decisions:
- How to provide the starting values
- Whether the resulting list should be mutable or immutable
This matters because not every list-like object in Java behaves the same way.
For example:
new ArrayList<>()creates a normal, mutable resizable list.Arrays.asList(...)creates a fixed-size list backed by an array.List.of(...)creates an immutable list in modern Java.
Your refactored version is a very common and good approach:
ArrayList<String> places = new ArrayList<>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata")
);
Why does this work well?
Arrays.asList(...)quickly creates a list from values.new ArrayList<>(...)copies those values into a real mutableArrayList.
This is useful because Arrays.asList(...) alone does not give you a fully flexible ArrayList.
In real programming, this concept matters whenever you:
- create test data
- define default options
- prepare seed values
- pass lists to methods
- decide whether data should be editable
The best choice depends on whether you need to later add or remove items.
Mental Model
Think of Java list initialization like packing items into a container.
Arrays.asList(...)is like putting items into a tray with fixed slots. You can replace an item in a slot, but you cannot add more slots or remove slots.new ArrayList<>(...)is like moving those items into a flexible bag that can grow or shrink.List.of(...)is like sealing the items in a display case: you can look at them, but you cannot change them.
So the real question is not just "How do I write this in one line?" It is also: What kind of list behavior do I want afterward?
Syntax and Examples
Common ways to initialize a list in Java
1. Mutable ArrayList with initial values
ArrayList<String> places = new ArrayList<>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata")
);
Use this when:
- you want a real
ArrayList - you may add or remove items later
Example:
ArrayList<String> places = new ArrayList<>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata")
);
places.add("Mendoza");
System.out.println(places);
Output:
[Buenos Aires, Córdoba, La Plata, Mendoza]
2. Fixed-size list with Arrays.asList(...)
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
Use this when:
- you only need a quick list
- you do not need to add or remove elements
Important:
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
places.add("Mendoza"); // throws UnsupportedOperationException
3. Immutable list with List.of(...) (Java 9+)
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
Use this when:
- the list should never change
- you want a concise modern style
Important:
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
places.add("Mendoza"); // throws UnsupportedOperationException
4. Recommended variable type: program to the interface
Often this is better than declaring ArrayList directly:
List<String> places = new ArrayList<>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata")
);
This is more flexible because your code depends on the List interface, not one specific implementation.
Step by Step Execution
Consider this example:
List<String> places = new ArrayList<>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata")
);
Here is what happens step by step:
- Java evaluates
Arrays.asList("Buenos Aires", "Córdoba", "La Plata"). - That creates a list containing three strings.
- That list is passed into the
ArrayListconstructor. - The constructor copies the elements into a new mutable
ArrayList. - The variable
placesnow refers to that newArrayList.
Now trace this code:
List<String> places = new ArrayList<>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata")
);
places.add("Mendoza");
System.out.println(places);
Execution:
- Start with
[ "Buenos Aires", "Córdoba", "La Plata" ] places.add("Mendoza")appends a new element.- Final list becomes:
[Buenos Aires, Córdoba, La Plata, Mendoza]
Compare that with this version:
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
places.add("Mendoza");
Execution:
Arrays.asList(...)creates a fixed-size list.places.add("Mendoza")tries to grow the list.- Java throws
UnsupportedOperationExceptionbecause this list cannot change size.
Real World Use Cases
This pattern appears often in real Java code.
Test data
List<String> testUsers = new ArrayList<>(Arrays.asList("alice", "bob", "carol"));
Useful for unit tests, mock data, and examples.
Default configuration values
List<String> supportedLocales = List.of("en", "es", "fr");
Good when values should not change.
API input preparation
List<Integer> ids = new ArrayList<>(Arrays.asList(10, 20, 30));
ids.add(40);
Useful when building request payloads dynamically.
Seed data for scripts or demos
List<String> cities = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
Good when you only need to iterate over a fixed set of values.
Real Codebase Usage
In real codebases, developers usually choose the initialization style based on mutability and readability.
Common patterns
Program to the List interface
List<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
This makes it easier to later change the implementation.
Use immutable lists for constants
private static final List<String> SUPPORTED_CITIES = List.of(
"Buenos Aires",
"Córdoba",
"La Plata"
);
This prevents accidental changes.
Copy before modifying external data
List<String> input = Arrays.asList("a", "b", "c");
List<String> editable = new ArrayList<>(input);
editable.add("d");
This is common when a method receives data but needs a mutable copy.
Validation and defensive coding
Developers often use immutable lists where possible because they reduce bugs caused by accidental mutation.
Test setup
In tests, short one-line list creation is common because readability matters more than reuse:
List<String> expected = List.of("Buenos Aires", "Córdoba", "La Plata");
Common Mistakes
1. Assuming Arrays.asList(...) returns a normal ArrayList
Broken example:
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
places.add("Mendoza");
Problem:
- This compiles.
- It fails at runtime with
UnsupportedOperationException.
Fix:
List<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
places.add("Mendoza");
2. Declaring the variable as ArrayList when List is enough
Less flexible:
ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Usually better:
List<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Why:
- it reduces coupling
- it makes refactoring easier
3. Trying to modify a List.of(...) list
Broken example:
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
places.remove(0);
Problem:
List.of(...)creates an immutable list.
Fix:
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
places.remove(0);
4. Using older verbose generic syntax unnecessarily
Older style:
ArrayList<String> places = new ArrayList<String>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Cleaner modern style:
ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
The diamond operator <> lets Java infer the generic type.
5. Forgetting Java version differences
List.of(...)requires Java 9+Arrays.asList(...)works in older Java versions
If you support older Java, Arrays.asList(...) is often the practical choice.
Comparisons
| Approach | Java Version | Mutable? | Can add/remove? | Notes |
|---|---|---|---|---|
new ArrayList<>() + add(...) | All | Yes | Yes | Most explicit, more lines |
Arrays.asList(...) | All | Partly | No | Fixed-size list |
new ArrayList<>(Arrays.asList(...)) | All | Yes | Yes | Common one-line mutable solution |
List.of(...) | Java 9+ | No | No | Concise immutable list |
new ArrayList<>(List.of(...)) | Java 9+ | Yes | Yes | Modern concise mutable copy |
Which one should you choose?
- Choose
Arrays.asList(...)if you only need a quick fixed-size list. - Choose
new ArrayList<>(Arrays.asList(...))if you want a mutable list in one line. - Choose
List.of(...)if the values should never change. - Prefer
List<String>as the variable type unless you specifically needArrayList.
Cheat Sheet
Quick reference
Mutable ArrayList in one line
List<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Fixed-size list
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
- Can replace values with
set(...) - Cannot
add(...)orremove(...)
Immutable list
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
- Cannot modify at all
- Java 9+
Mutable copy of immutable or fixed-size list
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
Best practice
List<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
- Prefer
Listas the variable type - Use
ArrayListwhen you need resizing - Use
List.of(...)for constants or read-only values
FAQ
Is Arrays.asList(...) the same as new ArrayList<>(...)?
No. Arrays.asList(...) returns a fixed-size list, while new ArrayList<>(...) creates a normal resizable list.
What is the best one-line way to create a mutable list in Java?
A common choice is:
List<String> items = new ArrayList<>(Arrays.asList("a", "b", "c"));
If you use Java 9+, this is also good:
List<String> items = new ArrayList<>(List.of("a", "b", "c"));
Should I declare the variable as List or ArrayList?
Usually List is better because it keeps your code flexible and less tied to one implementation.
Why does add() fail after using Arrays.asList(...)?
Because the returned list has a fixed size. It supports reading and replacing elements, but not growing or shrinking.
Is List.of(...) better than Arrays.asList(...)?
For immutable lists in modern Java, yes. It is more explicit about being unmodifiable.
Which approach is best for test data?
- Use
List.of(...)if the test data should not change. - Use
new ArrayList<>(...)if the test modifies the list.
Can I still use the multi-line add(...) approach?
Yes. It is perfectly valid and can be clearer when values are built gradually or conditionally.
Mini Project
Description
Create a small Java program that builds a list of city names for a test scenario. The project demonstrates the difference between a mutable list and an immutable or fixed-size list, and helps you practice choosing the right initialization style.
Goal
Build and modify a city list using one-line initialization, then print the results to verify which list types can be changed.
Requirements
- Create one list of cities using a one-line mutable
ArrayListinitialization. - Add one extra city to the mutable list.
- Create a second list using
List.of(...)orArrays.asList(...). - Print both lists.
- Show, in code or comments, which list can be modified and which cannot.
Keep learning
Related questions
Add External JAR Files to an IntelliJ IDEA Java Project
Learn how to add external JAR dependencies to an IntelliJ IDEA Java project using module libraries, and when to use Maven or Gradle instead.
Avoiding Java Code in JSP with JSP 2: EL and JSTL Explained
Learn how to avoid Java scriptlets in JSP 2 using Expression Language and JSTL, with examples, best practices, and common mistakes.
Call a Method After a Delay in Android Java
Learn how to run Java code after a delay in Android using Handler.postDelayed, manage the main thread, and cancel callbacks safely.