Collections.emptyList() vs. new instance
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Collections.emptyList() and new ArrayList<>() both represent an empty list, but they communicate different contracts. The first says “here is an empty immutable list,” while the second says “here is a new mutable list you can change.”
Collections.emptyList() Returns a Shared Immutable Empty List
Collections.emptyList() returns an empty list instance that cannot be modified.
Because the returned object is immutable and shared, it avoids creating a new list object every time. That makes it a strong default when a method simply needs to return “no results.”
This is especially useful for API methods that promise the caller a list but have nothing to return.
new ArrayList<>() Creates a Fresh Mutable Object
A new list instance is appropriate when the caller or the method itself needs mutability.
Each call allocates a new object, and callers can append, remove, or replace entries. That is not a downside when mutation is part of the design; it is simply a different contract.
Choose Based on Mutability, Not Habit
The most important question is not micro-performance. It is whether the returned list should be modifiable.
If the answer is no, returning Collections.emptyList() is clearer than returning a mutable list that just happens to be empty at the moment.
If the answer is yes, return a real mutable list.
That method clearly intends to build up a list over time, so a new instance is the correct tool.
Returning Empty Collections Is Better Than Returning null
A common API question sits behind this comparison: should a method return null when there is no data? In most Java APIs, the better answer is no.
Returning an empty list lets callers iterate safely without extra null checks.
That is a cleaner contract than forcing every caller to guard against null before basic list operations.
Immutability Protects Callers and Implementations
Returning an immutable empty list can prevent accidental coupling between the caller and your implementation.
That throws UnsupportedOperationException, which is a useful signal that the API never intended the list to be modified.
By contrast, returning a new mutable list invites callers to treat the result as their own working collection. That may be exactly what you want, but the choice should be explicit.
Minor Performance Differences Matter Less Than API Meaning
Yes, Collections.emptyList() avoids repeated allocation of empty list objects. In very hot code paths that can be a small win, but most of the time the bigger benefit is semantic clarity.
A shared immutable empty list communicates intent better than a fresh mutable list. In Java, that kind of contract clarity tends to matter more than saving one tiny allocation in isolation.
Common Pitfalls
- Returning
new ArrayList<>()by habit when the API should really promise immutability. - Returning
Collections.emptyList()and then expecting the caller to add items to it. - Treating the decision as purely a performance issue instead of a contract decision.
- Forgetting that immutable and mutable empties behave differently under modification attempts.
- Mixing both styles arbitrarily across the same API surface and making caller expectations inconsistent.
Summary
- '
Collections.emptyList()returns a shared immutable empty list.' - '
new ArrayList<>()creates a fresh mutable empty list.' - Choose based on whether mutation is part of the contract.
- Returning an empty list is usually better than returning
null. - The semantic difference matters more than the tiny allocation difference.
Related reading
- CollectionT versus ListT what should you use on your interfaces?
- Combinations from dictionary with list values using Python
- Combine json arrays by key, javascript
- Combining graphs is there a TensorFlow import_graph_def equivalent for C?
- Collision detection of huge number of circles
- Combinatorial optimization
- Collision detection between two rectangles in java
- Combining multiple SuppressWarnings annotations - Eclipse Indigo

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.