How to Convert an ArrayList to an Array in Java
Converting an ArrayList to an array is a common Java operation, but it comes with a few important pitfalls. One of the biggest surprises for beginners is that calling toArray() without any arguments returns an Object[] rather than the expected typed array. Another common challenge is converting a List<Integer> into a primitive int[], since Java generics work only with reference types.
In this guide, you'll learn the correct ways to convert an ArrayList to both Integer[] and int[], understand the famous toArray() trap, and discover the modern best practices recommended for Java developers.
Problem Statement
Given the following ArrayList:
List<Integer> list = new ArrayList<>(Arrays.asList(10, 20, 30));
Convert it into:
- A boxed
Integer[]array - A primitive
int[]array
Method 1: Using toArray() Without Arguments (The Trap)
The simplest-looking approach is:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> list =
new ArrayList<>(Arrays.asList(10, 20, 30));
Object[] array = list.toArray();
System.out.println(Arrays.toString(array));
}
}
Output
[10, 20, 30]
Why This Is a Problem
Although the values are correct, the returned type is:
Object[]
Attempting this:
Integer[] numbers = (Integer[]) list.toArray();
throws:
java.lang.ClassCastException
Explanation
The no-argument toArray() method always returns an Object[].
It does not preserve the generic type of the list.
Method 2: Using toArray(T[] a) (Recommended)
The correct approach is to provide a typed array.
Example
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> list =
new ArrayList<>(Arrays.asList(10, 20, 30));
Integer[] array = list.toArray(new Integer[0]);
System.out.println(Arrays.toString(array));
}
}
Output
[10, 20, 30]
Explanation
Passing a typed array tells Java exactly which array type should be created.
This is the standard and recommended approach for converting a list into an array.
Time Complexity: O(n)
Space Complexity: O(n)
Method 3: The Zero-Length Array Idiom
You'll often see this pattern:
Integer[] array = list.toArray(new Integer[0]);
instead of:
Integer[] array = list.toArray(new Integer[list.size()]);
Why?
Modern JVMs optimize the zero-length array pattern internally.
It has become the preferred and widely accepted idiom for converting collections into typed arrays.
Method 4: Convert to a Primitive int[]
Since Java generics don't support primitive types, toArray() cannot directly produce an int[].
Instead, use streams.
Example
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> list =
new ArrayList<>(Arrays.asList(10, 20, 30));
int[] array = list.stream()
.mapToInt(Integer::intValue)
.toArray();
System.out.println(Arrays.toString(array));
}
}
Output
[10, 20, 30]
Explanation
mapToInt() converts each boxed Integer into a primitive int.
The resulting array is a genuine primitive array.
Method 5: Using Java Streams
Java Streams can also produce a boxed array directly.
Example
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> list =
new ArrayList<>(Arrays.asList(10, 20, 30));
Integer[] array =
list.stream().toArray(Integer[]::new);
System.out.println(Arrays.toString(array));
}
}
Output
[10, 20, 30]
Explanation
Integer[]::new is a constructor reference that tells the stream which array type to create.
Step-by-Step Explanation
Suppose the list is:
[10, 20, 30]
Using toArray()
Java creates:
Object[]
Although the elements are integers, the array type is Object[].
Using toArray(new Integer[0])
Java creates:
Integer[]
The resulting array has the correct type and can be assigned directly.
Using Streams for int[]
Each Integer is unboxed:
Integer
↓
int
before being stored inside the primitive array.
Internal Working
toArray()
ArrayList
↓
Copies Elements
↓
Object[]
Generic type information is not preserved.
toArray(new Integer[0])
ArrayList
↓
Uses Integer Type
↓
Integer[]
Java creates the correct array type using the supplied array.
mapToInt().toArray()
List<Integer>
↓
Unboxing
↓
int[]
Each wrapper object becomes a primitive value.
Real-Life Analogy
Imagine asking a warehouse to pack your belongings.
If you simply say, "Give me a box," they'll provide a generic container.
If you hand them a sample box labeled Integer, they'll pack everything into the same type of container.
Similarly, toArray(new Integer[0]) tells Java exactly what type of array should be created.
Best Practices
- Use
toArray(new Integer[0])to obtain a properly typed array. - Use
mapToInt().toArray()when you need a primitiveint[]. - Prefer the zero-length array idiom over manually allocating
new Integer[list.size()]. - Use constructor references (
Integer[]::new) when working with streams. - Avoid casting the result of
toArray().
Common Mistakes
1. Casting Object[] to Integer[]
Incorrect:
Integer[] array =
(Integer[]) list.toArray();
This throws a ClassCastException.
2. Expecting toArray() to Return a Primitive Array
toArray() can only create arrays of reference types.
It cannot directly create int[].
3. Using Outdated Array Allocation Advice
Many older resources recommend:
new Integer[list.size()]
Today, the preferred idiom is:
new Integer[0]
4. Forgetting to Unbox
If you need an int[], remember to use:
mapToInt(Integer::intValue)
Otherwise, you'll end up with an Integer[].
Expert Tips
- The
Object[]returned bytoArray()is one of the most common Java interview pitfalls. - The zero-length array idiom (
new T[0]) is optimized by modern JVM implementations. - Constructor references such as
Integer[]::newprovide a clean and modern alternative when using streams. - Primitive arrays consume less memory than boxed arrays because they eliminate wrapper object overhead.
Comparison Table
| Method | Returns | Correctly Typed? |
|---|---|---|
list.toArray() |
Object[] |
❌ No |
list.toArray(new Integer[0]) |
Integer[] |
✅ Yes |
list.stream().mapToInt(...).toArray() |
int[] |
✅ Yes |
list.stream().toArray(Integer[]::new) |
Integer[] |
✅ Yes |
Frequently Asked Questions
1. Why does list.toArray() return Object[]?
Because Java's no-argument toArray() method always returns an Object[], regardless of the list's generic type.
2. How do I get an Integer[] from an ArrayList<Integer>?
Use:
Integer[] array =
list.toArray(new Integer[0]);
3. Why is new Integer[0] preferred over new Integer[list.size()]?
Modern JVMs optimize the zero-length array idiom, making it the recommended and widely accepted approach.
4. How do I convert a List<Integer> into a primitive int[]?
Use:
list.stream()
.mapToInt(Integer::intValue)
.toArray();
5. Can I cast list.toArray() to Integer[]?
No.
Doing so throws a ClassCastException because the actual returned type is Object[].
6. What does Integer[]::new mean?
It is a constructor reference that tells Java Streams to create an Integer[] of the required size.
7. Does converting a list to an array create a copy?
Yes.
The array is independent of the original list, so changes made to one do not affect the other.
8. How do I convert a List<String> to a String[]?
Use the same pattern:
String[] array =
list.toArray(new String[0]);
or
String[] array =
list.stream().toArray(String[]::new);