Java example

How to convert an array to a list in Java

7 min read Updated Sep 2026 Runs in an isolated runtime
Quick answer

For a list you can change, copy the array: new ArrayList<>(Arrays.asList(array)). Arrays.asList(array) on its own is a fixed-size view of the array, so add() throws UnsupportedOperationException. The other direction is list.toArray(new String[0]), and a primitive int[] needs a stream: Arrays.stream(nums).boxed().toList().

Java has three ready-made ways to wrap an array in a List, and they look alike but behave differently. Arrays.asList returns a view that shares the array's storage and can't grow. List.of (Java 9+) returns an unmodifiable copy that refuses null. Passing either to the ArrayList constructor gives you an ordinary list that is yours to change. This page covers all three, the int[] case where Arrays.asList quietly does the wrong thing, converting to a Set, and going back from a list to an array. Each example runs on this page: hit Run, then edit the code and run it again.

1new ArrayList<>(Arrays.asList(array))Recommended

This is the answer to "create an ArrayList from an array". Arrays.asList wraps the array without copying it, and the ArrayList copy constructor then copies the elements into a new list of its own. The result is a normal ArrayList<String>: you can add, remove and sort it, and nothing you do touches the original array. When the list already exists, Collections.addAll(list, array) appends the array's elements to it without the intermediate wrapper.

Main.java

Output

Prints [Java, Kotlin, Groovy], then the unchanged array [Java, Kotlin, Scala], then [Clojure, Java, Kotlin, Scala]. On Java 9+ you can also write new ArrayList<>(List.of(array)), but that throws if the array holds a null, while the Arrays.asList form copies nulls as they are. The array is printed with Arrays.toString because printing it directly shows a type and hash code instead of the contents; see print an array.

2Arrays.asList: a fixed-size view of the array

Arrays.asList(array) doesn't copy anything. It returns a list that reads and writes the array itself, so a set() on the list changes the array and an assignment to the array shows up in the list. Because an array can't change length, neither can the list: add(), remove() and clear() all throw UnsupportedOperationException. It is also not a java.util.ArrayList, despite the name of the class it returns.

Main.java

Output

The first two lines both print [JAVA, Kotlin, SCALA]: one change was made through the list and one through the array, and each side sees both. The class is java.util.Arrays$ArrayList, a private nested class, and the failed add prints add failed: java.lang.UnsupportedOperationException with no message. Anything that only replaces elements is allowed, which is why Collections.sort works and prints [1, 2, 3]. Use Arrays.asList when you need a cheap, read-mostly List over an array you already have, or for a short fixed list written inline as varargs; copy it as in section 1 as soon as the size has to change.

3List.of(array) (Java 9+): an unmodifiable copy

List.of also accepts an array, since its varargs parameter is an array. Unlike Arrays.asList, it copies the elements, so later changes to the array don't reach the list, and the list itself is fully unmodifiable: set() throws as well as add(). It also rejects null elements. That makes it a good fit for constants and return values that callers must not change, and a poor fit for data that might contain gaps.

Main.java

Output

Prints [Java, Kotlin, Scala] even though langs[0] became C# after the call, then set failed: java.lang.UnsupportedOperationException. With a null in the array, Arrays.asList prints [a, null, c] while List.of throws NullPointerException. To copy an existing collection rather than an array, use List.copyOf(collection) (Java 10+), which has the same rules. For writing lists inline, see initialize a list in one line.

4Which should you use?

MethodAdd / removeLinked to the arrayBest for
new ArrayList<>(Arrays.asList(arr))YesNo, a copyMost code: a list you will change
Arrays.asList(arr)No, fixed sizeYes, both waysA cheap view; set() and sort() still work
List.of(arr)No, unmodifiableNo, a copyRead-only data without nulls (Java 9+)
Collections.addAll(list, arr)YesNo, a copyAppending to a list you already have
Arrays.stream(arr).boxed().toList()No, unmodifiableNo, a copyPrimitive arrays such as int[] (Java 16+)

5Convert an array to a Set

The same copy-constructor pattern builds a Set, and the duplicates disappear on the way in. Which set you choose decides the order you get back. LinkedHashSet keeps the order in which values first appeared, TreeSet sorts them, and HashSet makes no promise about order at all. Set.of(array) (Java 9+) is the odd one out: it treats a duplicate as a mistake and throws.

Main.java

Output

Prints [java, go, rust] (first-seen order), [go, java, rust] (sorted), 3 true, then duplicate element: java, the message of the IllegalArgumentException from Set.of. The HashSet line prints only the size and a lookup because its iteration order is unspecified, and Set.of sets even change order from one run to the next. On Java 8, Arrays.stream(tags).collect(Collectors.toSet()) does the same job as the HashSet line. If all you need is one membership test, a set is overkill; see check if an array contains a value.

6Convert a list back to an array

list.toArray(new String[0]) is the classic answer to "convert ArrayList<String> to String[]". The empty array only tells toArray the element type, and it allocates a new array of the right size. Java 11 added toArray(String[]::new), which says the same thing with an array constructor. Avoid the no-argument toArray() when you want a typed array: it returns an Object[], and no cast turns that into a String[].

Main.java

Output

Prints [Java, Kotlin, Scala], 3 Scala, [JAVA, KOTLIN, SCALA], Object[], then cast failed: ClassCastException. The cast compiles, because an Object[] variable could hold a String[], but it fails at run time since this array really is an Object[]. You may see toArray(new String[list.size()]) in older code; it works too, and on current JVMs the zero-length form is at least as fast, so there is no reason to size the array yourself.

7Primitive arrays: int[] to List<Integer> and back

Arrays.asList is declared as <T> List<T> asList(T... a), and a type parameter can't be a primitive. Pass it an int[] and Java picks T = int[], so you get a List<int[]> whose one element is the whole array. It compiles without a warning. To get a List<Integer>, stream the array and box each value with boxed(). The reverse trip, List<Integer> to int[], unboxes with mapToInt.

Main.java

Output

Prints 1, the size of the accidental List<int[]>, then [3, 1, 4, 1, 5], [3, 1, 4, 1, 5, 9], and the same values again as an int[]. Stream.toList() (Java 16+) returns an unmodifiable list; on Java 8 use .collect(Collectors.toList()), or Collectors.toCollection as above when you need a guaranteed ArrayList. A boxed Integer[] has no such trap: Arrays.asList handles it like any other object array. The same streams exist for the other primitives, such as Arrays.stream(double[]) with mapToDouble.

Frequently asked questions

What is the difference between Arrays.asList() and new ArrayList<>(Arrays.asList())?

Arrays.asList(array) returns a fixed-size list backed by the array: changes through set() show up in the array and vice versa, and add() or remove() throw UnsupportedOperationException. Wrapping it in new ArrayList<>(...) copies the elements into an independent, resizable java.util.ArrayList, so the array and the list no longer affect each other.

Why does Arrays.asList() throw UnsupportedOperationException when I call add()?

Because the list it returns is a view over the array, and an array cannot change length. Every size-changing call (add, remove, clear, addAll) throws, while set and in-place sorting work. If you need to add or remove elements, copy it first: List<String> list = new ArrayList<>(Arrays.asList(array));.

Why does Arrays.asList(int[]) not return a List<Integer>?

Generics do not work with primitives, so for an int[] the type parameter becomes int[] itself and you get a List<int[]> with one element. Box the values with a stream instead: Arrays.stream(nums).boxed().toList() on Java 16+, or .collect(Collectors.toList()) on Java 8. An Integer[] works with Arrays.asList directly.

Should I pass new String[0] or new String[list.size()] to toArray()?

Use new String[0], or toArray(String[]::new) on Java 11+. Both produce a correctly sized String[], and on current JVMs the zero-length version is at least as fast as presizing. If you do pass an array that is larger than the list, toArray fills it and sets the slot after the last element to null: a 3-element list copied into a 5-element array gives [x, y, z, null, 5].

How do I convert a List<Integer> that contains null to an int[]?

list.stream().mapToInt(Integer::intValue).toArray() throws NullPointerException at the first null, because a null cannot be unboxed to an int. Decide what a null should become and map it explicitly, for example list.stream().mapToInt(i -> i == null ? 0 : i).toArray(), which turns [1, null, 3] into [1, 0, 3]. Or drop the nulls first with .filter(Objects::nonNull).

Is List.of(array) the same as Arrays.asList(array)?

No. List.of (Java 9+) copies the elements into a fully unmodifiable list: set() throws too, later changes to the array do not show up, and null elements are rejected with NullPointerException. Even List.of("a", "b").contains(null) throws, where Arrays.asList("a", "b").contains(null) just returns false. Arrays.asList is a live, fixed-size view that allows set() and nulls.

Run it yourself

Open any of these in the full Java editor: tweak, run, and share.

Java playground