Convert Array to ArrayList in Java (Mutable and Unmodifiable)

Convert array to ArrayList in Java with new ArrayList<>(Arrays.asList()), List.of() or streams. Covers fixed-size views, int[] arrays and the way back.

The array apple, banana, cherry with two lists. Arrays.asList points to the same array, so set() writes into it. new ArrayList holds its own copy, so add() works and the array stays unchanged

The standard way to convert an array to an ArrayList in Java is new ArrayList<>(Arrays.asList(array)), which wraps the array in a list view and copies its elements into a new list. The copy is a regular, mutable ArrayList that does not depend on the array, so we can add and remove elements freely.

We convert arrays to lists when an API gives us an array, such as String.split(), a varargs parameter or an older library method, and the rest of the code works with collections.

The following example converts a String array to a mutable list, an unmodifiable list, and an int array to a list of Integer.

String[] fruits = {"apple", "banana", "cherry"};
List<String> mutable = new ArrayList<>(Arrays.asList(fruits));           // [apple, banana, cherry]
List<String> readOnly = List.of(fruits);                                 // [apple, banana, cherry]
int[] scores = {90, 75, 82};
List<Integer> boxed = Arrays.stream(scores).boxed().collect(Collectors.toCollection(ArrayList::new));    // [90, 75, 82]

The first list accepts add(), the second throws on any change, and the third needs a stream because Arrays.asList() does not box primitives. We look at each kind of list, the view returned by Arrays.asList(), primitive arrays, and the way back from list to array.

1. Convert Array to ArrayList by Copying the Elements

The constructor ArrayList(Collection) copies every element of the given collection, so wrapping the array with Arrays.asList() first is the standard one-line conversion. The new list has its own internal array, and later changes to the original array do not reach it.

The array apple, banana, cherry with two lists. Arrays.asList points to the same array, so set() writes into it. new ArrayList holds its own copy, so add() works and the array stays unchanged
Arrays.asList() is a fixed-size view of the array, whereas new ArrayList<>() copies the elements into a separate list
String[] fruits = {"apple", "banana", "cherry"};
List<String> basket = new ArrayList<>(Arrays.asList(fruits));
basket.add("mango");                                                     // basket = [apple, banana, cherry, mango]
fruits[0] = "kiwi";
String firstInBasket = basket.get(0);                                    // "apple"

When the target list already exists, Collections.addAll() appends the array elements to it without the intermediate view. A stream with Collectors.toCollection(ArrayList::new) gives an ArrayList too, and it fits when we filter or map the elements on the way.

String[] moreFruits = {"plum", "fig"};
List<String> basket = new ArrayList<>(List.of("apple"));
boolean changed = Collections.addAll(basket, moreFruits);                // true
List<String> longNames = Arrays.stream(moreFruits)
    .filter(name -> name.length() > 3)
    .collect(Collectors.toCollection(ArrayList::new));                   // [plum]

We avoid casting the result of Collectors.toList() to ArrayList, because that collector gives no guarantee about the list type. The adding multiple elements to an ArrayList article shows more ways to fill an existing list.

2. Arrays.asList() Returns a Fixed-Size View

The method Arrays.asList() does not copy anything. It returns a list backed by the array, so the list and the array share the same elements, and the size of the list is fixed to the length of the array.

  • The call set() on the list writes into the array, and an assignment to the array shows up in the list.
  • The calls add() and remove() throw an UnsupportedOperationException, because the array cannot grow or shrink.
  • The class of the result is java.util.Arrays$ArrayList, a private class that only shares the simple name with java.util.ArrayList.
String[] fruits = {"apple", "banana", "cherry"};
List<String> view = Arrays.asList(fruits);
String previous = view.set(1, "blueberry");                              // "banana"
String inArray = fruits[1];                                              // "blueberry"
boolean added = view.add("mango");                                       // UnsupportedOperationException

The result of Arrays.asList() is not a mutable list, so code that calls add() on it fails at runtime, not at compile time. A view is still useful when we only read the elements or replace them in place, for example to sort the array through Collections.sort(view). The article on Arrays.asList() vs new ArrayList() compares both in more detail.

3. Convert an Array to an Unmodifiable List

When callers must not change the list, we create an unmodifiable one. The three JDK options look alike but differ in whether they copy the array and whether they accept null.

String[] fruits = {"apple", "banana", "cherry"};
List<String> copied = List.of(fruits);                                   // [apple, banana, cherry]
List<String> streamed = Arrays.stream(fruits).toList();                  // [apple, banana, cherry]
List<String> wrapped = Collections.unmodifiableList(Arrays.asList(fruits));    // [apple, banana, cherry]
fruits[0] = "kiwi";
String firstCopied = copied.get(0);                                      // "apple"
String firstWrapped = wrapped.get(0);                                    // "kiwi"

Notice that wrapped changed when we modified the array, because Collections.unmodifiableList() only blocks changes through the list and still reads the array underneath. A class that receives an array in its constructor and exposes it as a list uses List.of() or toList(), so later changes to the caller’s array do not leak in.

MethodCopies the array?null elementsSince
List.of(array)YesNullPointerExceptionJava 9
Arrays.stream(array).toList()YesAllowedJava 16
Collections.unmodifiableList(Arrays.asList(array))No, read-only viewAllowedJava 1.2
Guava ImmutableList.copyOf(array)YesNullPointerExceptionGuava

Projects that use Guava can call ImmutableList.copyOf() for an immutable list and Lists.newArrayList() for a mutable one. The JDK methods do the same job, so Guava is not needed for this conversion alone. The immutable collections factory methods article explains the List.of() family.

String[] fruits = {"apple", "banana"};
List<String> guavaImmutable = ImmutableList.copyOf(fruits);              // [apple, banana]
List<String> guavaMutable = Lists.newArrayList(fruits);                  // [apple, banana]

4. Converting a Primitive Array (int[]) to an ArrayList

A fitness app stores the heart rates of a workout in an int[] and needs a List<Integer> for a charting library. Generics work only with objects, so Arrays.asList() treats the whole int[] as one element and returns a List<int[]> of size 1.

int[] heartRates = {72, 95, 130};
List<int[]> wrong = Arrays.asList(heartRates);
int wrongSize = wrong.size();                                            // 1

The method Arrays.stream() has overloads for int[], long[] and double[], and boxed() turns each value into its wrapper object.

int[] heartRates = {72, 95, 130};
List<Integer> rates = Arrays.stream(heartRates).boxed().collect(Collectors.toCollection(ArrayList::new));    // [72, 95, 130]
List<Integer> readOnlyRates = Arrays.stream(heartRates).boxed().toList();                                     // [72, 95, 130]
List<Integer> guavaView = Ints.asList(heartRates);                                                         // [72, 95, 130]

Guava’s Ints.asList() returns a fixed-size view backed by the int[], like Arrays.asList() does for object arrays. For a char[] or byte[], the JDK has no stream overload, so we use a loop or Guava’s Chars.asList() and Bytes.asList().

5. Converting the ArrayList Back to an Array

The reverse direction uses toArray(). Since Java 11, the overload that takes an array constructor reference returns an array of the right type, and for Integer lists, mapToInt() unboxes the values into an int[].

List<String> basket = new ArrayList<>(List.of("apple", "fig"));
String[] asArray = basket.toArray(String[]::new);                        // [apple, fig]
List<Integer> rates = List.of(72, 95, 130);
int[] primitives = rates.stream().mapToInt(Integer::intValue).toArray();    // [72, 95, 130]

The Java List guide covers the other list operations once the data is in a list.

6. Array to ArrayList FAQs

Once the first conversion compiles, the next questions concern the shared view and the cost of each method.

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

The first returns a fixed-size view that shares the array, and the second copies the elements into an independent, growable ArrayList. We use the copy whenever the code adds or removes elements.

6.2. Why does Arrays.asList(int[]) return List?

The method takes a varargs parameter of a generic type T, and T cannot be a primitive type. Java therefore binds T to int[] and passes the whole array as one element. We use Arrays.stream(array).boxed() instead, as shown in section 4.

6.3. Does changing the array change the ArrayList?

No, not for new ArrayList<>(Arrays.asList(array)), because the constructor copies the element references. Both still point to the same element objects, so changing a field inside a mutable element is visible through both.

6.4. Which way of converting an array to a list is the fastest?

The constructor, Collections.addAll() and List.of() all copy each element once, so their cost grows with the array length in the same way. A stream adds some overhead per element, which matters only for very large arrays in hot code paths. The view from Arrays.asList() copies nothing, so it is the cheapest when a read-only, fixed-size list is enough.

6.5. How do we convert an array to a Set instead of a List?

We pass the same view to a set constructor, which also removes duplicates. The HashSet to ArrayList article shows the opposite direction.

String[] tags = {"red", "blue", "red"};
Set<String> uniqueTags = new LinkedHashSet<>(Arrays.asList(tags));     // [red, blue]

7. Conclusion

For a mutable list, we convert an array to an ArrayList with new ArrayList<>(Arrays.asList(array)), or with Collections.addAll() when the list already exists. For a read-only list, List.of(array) and Arrays.stream(array).toList() take a copy, whereas Collections.unmodifiableList() keeps following the array.

The view from Arrays.asList() is fixed in size and writes through to the array, and it does not work with primitive arrays. For an int[], we stream it and call boxed().

8. References

Happy Learning !!

Source Code on Github

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.