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:

Advertisement
 
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.


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 primitive int[].
  • 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 by toArray() 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[]::new provide 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);