Converting an Array to List(or ArrayList) in Java - Options and their analysis
Converting an array of data into an equivalent List does seem like one of the simplest tasks which a programmer would do when coding in Java. Thinking on the same lines I set out to write a simple and short corsding tip on array to list conversion, but in the process discovered so much underlying subtext/knowledge about the 3 primary options to do so that I decided to write a full-fledged full length post on the topic. In case you need a list of quick suggestions with examples on ways to convert an array to a list(or arraylist) then you can just read the code snippets which are self-explanatory. Else, do read on to understand the interesting bit of technical information around these array to list conversion options, which has several good-to-know technical nuggets interspersed throughout.
There are many scenarios where data is present in an
OUTPUT of the above code
As you can see in the output, members of
However, there are couple of limitations with the above instance of
Now running the above code, which tries to add an element to
Limitation 1 of using
To find out the issue, I ran this code with debugging option on in IntelliJ IDEA to see the 'type' of concrete
As you can see in the screenshot above, the type of
The next logical question is - why does the
The answer to this question is that instead of extending
Similarly,
So, the first consideration to take when deciding to use
Limitation 2 of using
Any changes done to the original array,
OUTPUT of the above code
As you can see in the above code and output, the value of
So, the second consideration to take when using
To summarize - Taking the 2 limitations of
Let us now look at the other options available to us for converting an array to a
OUTPUT of the above code
As you can infer from the above code and its output,
This method is good but not perfect. The limitation with this option is that it works only with arrays of
Option 3: Using Java 8’s
OUTPUT of the above code
In the above code, arrays of both primitive and
The only difference between the code for creation of a primitive vs
There are many scenarios where data is present in an
Array
, while you need to store it in a List
or, in List
’s more specific subclass, an ArrayList
. There are more than one commonly used ways in which an Array
can be converted to a List
or ArrayList
. Each of these methods come with their own limitations. This tutorial analyzes the three most commonly used options along with their limitations and applicability.
Option 1: Using Arrays.asList()
method to convert from an array to a List
This is one of the most common way of converting an array T[]
to a List<T>
using the Arrays.asList()
method. It can be coded for in a single line of code as shown next -Converting array to List using Arrays.asList()
package com.javabrahman.corejava;
import java.util.Arrays;
import java.util.List;
public class ArrayToList {
public static void main(String args[]){
Integer integerArray[] = {1,66,88,100, 201};
List<Integer> integerList= Arrays.asList(integerArray);
System.out.println(integerList);
}
}
[1, 66, 88, 100, 201]
integerList
have been copied from integerArray
. This is what we wanted to do as well.However, there are couple of limitations with the above instance of
List<Integer>
. Let us tackle these limitations one at a time. To start with, let us add the a new line to the above code which adds another number to integerList
as shown below - Adding a number to integerList after it is created
Integer integerArray[] = {1,66,88,100, 201};
List<Integer> integerList= Arrays.asList(integerArray);
integerList.add(250);
integerList
, throws the following exception - Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at com.javabrahman.corejava.ArrayToList.main(ArrayToList.java:9)
What could have gone wrong with the above code?
It was converted to a List
correctly. The List
elements were also printed correctly. Then why is UnsupportedOperationException
thrown when we try to add an element to the List
?Limitation 1 of using
List
instance returned by Arrays.asList()
methodTo find out the issue, I ran this code with debugging option on in IntelliJ IDEA to see the 'type' of concrete
List
instance created by Arrays.asList()
method. Here is what I saw - List
instance created is mentioned as Arrays$ArrayList
. integerList
is not an instance of java.util.ArrayList
as one would assume. Rather, it is an instance of a static nested class of Arrays
class named ArrayList
(denoted as Arrays$ArrayList
).add()
operation on Arrays$ArrayList
instance throw an UnsupportedOperationException
?The answer to this question is that instead of extending
java.util.List
, Arrays$ArrayList
instead extends an abstract class named java.util.AbstractList
. When add()
method is invoked on an Arrays$ArrayList
instance, it actually invokes AbstractList
’s inherited add()
method, as Arrays$ArrayList
doesn't have any overridden implementation for add()
method. The default implementation of add()
method in AbstractList
throws an UnsupportedOperationException
, and that is what we saw above.Similarly,
UnsupportedOperationException
will be thrown if remove()
method is called on the integerList
variable of type Arrays$ArrayList
. The List
of type Arrays$ArrayList
has been defined as a fixed size list. Elements cannot be added or removed from this List.So, the first consideration to take when deciding to use
Arrays.asList()
method to convert an array to a List
is to check if you will ever need to modify the contents of the resulting List
. If yes, then you can skip the Arrays.asList()
method which gets you an equivalent "read-only" List
instance. If you don't need to modify the List
then before finalizing on Arrays.asList()
you need to keep in mind its second limitation which is covered next.Limitation 2 of using
List
instance returned by Arrays.asList()
methodAny changes done to the original array,
integerArray
in our example, will reflect in the List
instance, integerList
, even if the changes are done in the array after the list was created. Let us see a code snippet showing the effect of this limitation -
Second limitation of using Arrays.asList()
Integer integerArray[] = {1,66,88,100, 201};
List<Integer> integerList = Arrays.asList(integerArray);
System.out.println(integerList);
integerArray[0] = 22;
System.out.println(integerList);
[22, 66, 88, 100, 201]
integerArray[0]
was changed in the above code after the integerList
was created. This change reflected in the integerList
as well. This is because, the Arrays$ArrayList
instance internally stores a reference to the array passed to it at the time of initialization, and uses the original array itself to store data. Hence, any change done to the original array is automatically propagated to the Arrays$ArrayList
instance created out of it.So, the second consideration to take when using
Arrays.asList()
method is to accept that given any change to the original array, the generated list will also change.To summarize - Taking the 2 limitations of
Arrays.asList()
together, if the list created out of the array does not need to be modified post-creation, and you are fine with any changes in original array propagating into the list post-creation, then Arrays.asList()
is a good option for converting an array
into a List
.Let us now look at the other options available to us for converting an array to a
List
.
Option 2: Using ArrayList
constructor with Arrays.asList()
as parameter
We can use the constructor of an ArrayList
which accepts a collection as an input parameter and initializes a new java.util.ArrayList
instance containing the collection's data. An ArrayList
created in this manner does not have the twin disadvantages we saw in option 1 viz. being of fixed size, and being just another view into the original array rather than being an ArrayList
instance on its own.
Let us now see a code snippet showing this option in use -
Creating a new ArrayList instance using constructor with collection as input
package com.javabrahman.corejava;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ArrayToList {
public static void main(String args[]){
Integer integerArray[] = {1,66,88,100, 201};
List<Integer> integerList= new ArrayList<>(Arrays.asList(integerArray));
System.out.println(integerList);
//Modifying the original array
integerArray[0]=22;
System.out.println(integerList);
//Adding a new number to integerList
integerList.add(250);
System.out.println(integerList);
}
}
[1, 66, 88, 100, 201] [1, 66, 88, 100, 201] [1, 66, 88, 100, 201, 250]
integerList
created like this allows adding a new number(250) to the ArrayList
. Also, the original array's modification (by setting integerArray[0]=22
) does not affect the newly created integerList
which is now an independent instance in itself.This method is good but not perfect. The limitation with this option is that it works only with arrays of
Object
/Class
types and not with primitives such as int
or long
. This is because a List
cannot be of a primitive type, and due to the same reason Arrays.asList()
method also does not accept a primitive array as its input. This limitation when converting arrays of primitive types to lists, now takes us to the third way for creating a list from a given array.Option 3: Using Java 8’s
Arrays.stream()
method with a Collector
Java 8’s Arrays
class provides a method stream()
which has overloaded versions accepting both primitive arrays and Object
arrays.
Let us see a code snippet showing Java 8's new Arrays.stream()
method is use -
Converting array to List using Arrays.stream() and a Collector
package com.javabrahman.corejava;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class ArrayToList {
public static void main(String args[]){
//Converting a primitive 'int' array to List
int intArray[] = {1, 11, 111, 1111, 10000};
List<Integer> integerList = Arrays.stream(intArray).boxed().collect(Collectors.toList());
System.out.println(integerList);
//Converting an 'Integer'array to List
Integer integerArray[] = {2, 22, 222, 2222, 20000};
List<Integer> integerList2 = Arrays.stream(integerArray).collect(Collectors.toList());
System.out.println(integerList2);
}
}
[1, 11, 111, 1111, 10000] [2, 22, 222, 2222, 20000]
Object
types are converted to streams of their respective types first. The individual Streams are then fed, or pipelinedClick to Read tutorial explaining concept of Pipelines in Computing, to a Collector
instance which accepts the Stream
as input and 'collects' its elements into a List
which is of the same type as the type of the original array.The only difference between the code for creation of a primitive vs
Object
type List
is the boxed()
method. The boxed()
method is used to convert the IntStream
(a stream of primitive int
type) instance returned by the stream()
method for the primitive intArray
, into corresponding Integer
type Stream
instance. boxed()
is needed for int
arrays because a List
collector requires a stream of an Object
type rather than a primitive IntStream
.
Summary
In this tutorial we had an in-depth look at the 3 popularly used ways of converting a given array into an equivalent arraylist. We looked at how to code for each of these options, understood their applicability and went through their limitations.