List to Array in Java

29 views

In this article, we’ll go through all the ways possible to convert a list to an array in Java.

1. How to Convert a List to Array in Java

There are many ways to convert a list to an array in Java; you can either do it by using a loop (for, for each, java 8 forEach, while) or use one of the existing methods of Collection interface. We’ll go through all of them in the following sections.

Before we begin, we need to know what a shallow and a deep copy is:

A shallow copy is when the new object (e.g. the array we will convert the list to) will have the same references as the original list. This means that if we change any internal value of the list, this value will also change in the array and vice-versa.

A deep copy is when the new object (e.g. the array we will convert the list to) will have different references than the original list. This means that the 2 objects (the list and the array) will not be affected by each other.

Note that you do not have to worry about shallow and deep copies when dealing with primitives or Strings.

2. Converting a List to an Array Using Collection.toArray methods

The following methods make it as easy as possible to convert a list to an array, but you should be careful when dealing with custom-made objects as the conversion will be done through a shallow copy.

2.1 Object[] toArray()

This method only allows you to convert your list to an array of type Object[]. Consider the example above:

List<String> names = Arrays.asList(
        "Georgios",
        "Nikolaos",
        "Dimitrios",
        "Ioannis"
);
Object[] namesArray = names.toArray();

The above example will return an array of type Object which will have the 4 names of the list.

2.2 T[] toArray(T[] a)

This method accepts an array that will be populated with the values of the list and returns an array of the specified type.

List<String> names = Arrays.asList(
        "Georgios",
        "Nikolaos",
        "Dimitrios",
        "Ioannis"
);
String[] namesArray = names.toArray(new String[0]);

2.3 default T[] toArray(IntFunction generator)

This method accepts an IntFunction generator which will be used exactly like the previous method, but now we must pass a lambda expression or a method reference.

List<String> names = Arrays.asList(
        "Georgios",
        "Nikolaos",
        "Dimitrios",
        "Ioannis"
);
String[] namesArray = names.toArray(String[]::new); // This is exactly the same as the below line of code
String[] namesArray = names.toArray(i -> new String[0]);

Note that if you use a lambda expression and not the method reference, the number inside the brackets (new String[number]) should be equal to or less than the size of the list. If you do try to use a different number like 5 in the example where the list is of size 4, the new array will have size 5 with the 5th place being null.

3. The Shallow Copy Problem

Consider that we do not have a list of strings but a list of objects of type Person (A simple POJO with attributes name and surname):

Now let’s look at the example below:

 List<Person> authors = Arrays.asList(
         new Person("G", "P"),
         new Person("D", "T"),
         new Person("I", "M")
 );
 Person[] authorsArray = authors.toArray(Person[]::new);
 authors.get(0).setName("X");
 System.out.println(authorsArray[0]); // Will print Person{name='X', surname='P'}

As you can observe, even though we changed the name of the person belonging to the list, this affected our new array. In the following section, we’ll see how we can resolve this.

4. Converting a List to an Array Using Loops

In order to perform a deep copy to create our array, we need to do it manually via loops. In the following sections we’ll use the same list as before:

 List<Person> authors = Arrays.asList(
         new Person("G", "P"),
         new Person("D", "T"),
         new Person("I", "M")
 );

We will also create a copy constructor to accommodate our needs:

public Person(Person other) {
    this.name = other.name;
    this.surname = other.surname;
}

4.1 Using Simple For Loop

Person[] authorsArray = new Person[authors.size()];
for (var i = 0; i < authorsArray.length; i++) {
    authorsArray[i] = new Person(authors.get(i));
}

Now let’s try changing a value to the list and see if it will affect our array:

//Change a value in list
authors.get(0).setName("Hello");
System.out.println(authorsArray[0]); // Will print Person{name='G', surname='P'}
// Change a value in array
authorsArray[2].setName("World");
System.out.println(authors.get(2)); // Will print Person{name='I', surname='M'}

As you can observe, neither setting the name of a person inside the list will affect the person inside the array nor the reverse.

4.2 Using Enhanced For Loop

Person[] authorsArray = new Person[authors.size()];
int i = 0;
for (var person : authors) {
    authorsArray[i] = new Person(authors.get(i));
    i++;
}

4.3 Using While Loop

Person[] authorsArray = new Person[authors.size()];
int i = 0;
Iterator<Person> it = authors.iterator();
while (it.hasNext()){
    authorsArray[i] = new Person(it.next());
    i++;
}

4.4 Using Java 8 forEach

Person[] authorsArray = new Person[authors.size()];
AtomicInteger i = new AtomicInteger(0);
authors.forEach(name -> {
    authorsArray[i.get()] = new Person(authors.get(i.get()));
    i.incrementAndGet();
});

5. Converting a List to a Primitive Array

The only way to convert a list to a primitive array is to use one of the loops in sections 4.1-4.4 as methods Collection.toArray won’t work. Below you can find an example:

List<Integer> numbers =  Arrays.asList(1, 2, 3, 4, 5);
int[] numbersArray = new int[numbers.size()];
for (var i = 0; i < numbersArray.length; i++) {
    numbersArray[i] = numbers.get(i);
}

6. Conclusion

By now you should be able to convert a list to an array while knowing when you need a shallow or a deep copy. You can find the source code on our GitHub page.

Related Posts