Java Arrays

Creating a List from an Array

The Arrays.asList() method can be used to return a fixed-size list containing the elements of the given array.. The resulting List will be of the same parameter type as the base type of the array.

String[] stringArray = {"foo", "bar", "baz"};
List stringList = Arrays.asList(stringArray);

Note: This list is backed by (a view of) the original array, meaning that any changes to the list will change the array and vice versa. However, changes to the list that would change its size (and hence the array length) will throw an exception.

To create a copy of the list, use the constructor of java.util.ArrayList taking a Collection as an argument:

Version ≥ Java SE 5
String[] stringArray = {"foo", "bar", "baz"};
List stringList = new ArrayList(Arrays.asList(stringArray));
Version ≥ Java SE 7

In Java SE 7 and later, a pair of angle brackets (empty set of type arguments) can be used, which is called the Diamond. The compiler can determine the type arguments from the context. This means the type of information can be left out when calling the constructor of Array List and it will be inferred automatically during compilation. This is called Type Inference which is a part of Java Generics.

// Using Arrays.asList()
String[] stringArray = {"foo", "bar", "baz"};
List stringList = new ArrayList<>(Arrays.asList(stringArray));

// Using ArrayList.addAll()

String[] stringArray = {"foo", "bar", "baz"};
ArrayList list = new ArrayList<>();
list.addAll(Arrays.asList(stringArray));

// Using Collections.addAll()

String[] stringArray = {"foo", "bar", "baz"};
ArrayList list = new ArrayList<>();
Collections.addAll(list, stringArray);

A point worth noting about the Diamond is that it cannot be used with Anonymous Classes.

Version ≥ Java SE 8
// Using Streams

int[] ints = {1, 2, 3};
List list = Arrays.stream(ints).boxed().collect(Collectors.toList());

String[] stringArray = {"foo", "bar", "baz"};
List

Important notes related to using Arrays.asList() method

  • This method returns List, which is an instance of Arrays$ArrayList(static inner class of Arrays) and not java.util.ArrayList. The resulting List is of fixed-size. That means, adding or removing elements is not supported and will throw an UnsupportedOperationException:
stringList.add("something"); // throws java.lang.UnsupportedOperationException
  • A new List can be created by passing an array-backed List to the constructor of a new List. This creates a new copy of the data, which has the changeable size and that is not backed by the original array:
List modifiableList = new ArrayList<>(Arrays.asList("foo", "bar"));
  • Calling List asList(T… a) on a primitive array, such as an int[], will produce a List whose only element is the source primitive array instead of the actual elements of the source array.

The reason for this behavior is that primitive types cannot be used in place of generic type parameters, so the entire primitive array replaces the generic type parameter in this case. In order to convert a primitive
array to a List, first of all, convert the primitive array to an array of the corresponding wrapper type (i.e. call Arrays.asList on an Integer[] instead of an int[]).

Therefore, this will print false:

int[] arr = {1, 2, 3}; // primitive array of int
System.out.println(Arrays.asList(arr).contains(1));

On the other hand, this will print true:

Integer[] arr = {1, 2, 3}; // object array of Integer (wrapper for int)
System.out.println(Arrays.asList(arr).contains(1));

This will also print true, because the array will be interpreted as an Integer[]):

System.out.println(Arrays.asList(1,2,3).contains(1));

Creating an Array from a Collection

Two methods in java.util.Collection create an array from a collection:

  • Object[] toArray()
  • T[] toArray(T[] a)

Object[] toArray() can be used as follows:

Version ≥ Java SE 5
Set set = new HashSet();
set.add("red");
set.add("blue");
// although set is a Set, toArray() returns an Object[] not a String[]
Object[] objectArray = set.toArray();

T[] toArray(T[] a) can be used as follows:

Version ≥ Java SE 5
Set set = new HashSet();
set.add("red");
set.add("blue");

// The array does not need to be created up front with the correct size.
// Only the array type matters. (If the size is wrong, a new array will
// be created with the same type.)
String[] stringArray = set.toArray(new String[0]);

// If you supply an array of the same size as collection or bigger, it
// will be populated with collection values and returned (new array
// won't be allocated)
String[] stringArray2 = set.toArray(new String[set.size()]);

The difference between them is more than just having untyped vs typed results. Their performance can differ as well (for details please read this performance analysis section):

  • Object[] toArray() uses vectorized arraycopy, which is much faster than the type-checked arraycopy used in T[] toArray(T[] a).
  • T[] toArray(new T[non-zero-size]) needs to zero-out the array at runtime, while T[] toArray(new T[0]) does not. Such avoidance makes the latter call faster than the former. The detailed analysis here: Arrays of Wisdom of the Ancients.

Version ≥ Java SE 8

Starting from Java SE 8+, where the concept of Stream has been introduced, it is possible to use the Stream
produced by the collection in order to create a new Array using the Stream.toArray method.

String[] strings = list.stream().toArray(String[]::new);

Multidimensional and Jagged Arrays

It is possible to define an array with more than one dimension. Instead of being accessed by providing a single index, a multidimensional array is accessed by specifying an index for each dimension. The declaration of the multidimensional array can be done by adding [] for each dimension to a regular array declaration. For instance, to make a 2-dimensional int array, add another set of brackets to the declaration, such as int[][]. This continues for 3-dimensional arrays in java (int[][][]) and so forth.

To define a 2-dimensional array with three rows and three columns:

int rows = 3;
int columns = 3;
int[][] table = new int[rows][columns];

The array can be indexed and assign values to it with this construct. Note that the unassigned values are the default values for the type of an array, in this case, 0 for int.

table[0][0] = 0;
table[0][1] = 1;
table[0][2] = 2;

It is also possible to instantiate a dimension at a time and even make non-rectangular arrays. These are more commonly referred to as jagged arrays.

int[][] nonRect = new int[4][];

It is important to note that although it is possible to define any dimension of the jagged array, it’s preceding level must be defined.

// valid
String[][] employeeGraph = new String[30][];

// invalid
int[][] unshapenMatrix = new int[][10];

// also invalid
int[][][] misshapenGrid = new int[100][][10];
How Multidimensional Arrays are represented in Java

Jagged array literal intialization

Multidimensional arrays and jagged arrays can also be initialized with a literal expression. The following declares and populates a 2×3 int array:

int[][] table = {
    {1, 2, 3},
    {4, 5, 6}
};

Note: Jagged subarrays may also be null. For instance, the following code declares and populates a two-dimensional int array whose first subarray is null, the second subarray is of zero length, the third subarray is of one
length and the last subarray is a two-length array:

int[][] table = {
    null,
    {},
    {1},
    {1,2}
};

For multidimensional array it is possible to extract arrays of lower-level dimension by their indices:

int[][][] arr = new int[3][3][3];
int[][] arr1 = arr[0]; // get first 3x3-dimensional array from arr
int[] arr2 = arr1[0];  // get first 3-dimensional array from arr1
int[] arr3 = arr[0];   // error: cannot convert from int[][] to int[]

ArrayIndexOutOfBoundsException

The ArrayIndexOutOfBoundsException is thrown when a non-existing index of an array is being accessed.

Arrays are zero-based indexed, so the index of the first element is 0 and the index of the last element is the array capacity minus 1 (i.e. array.length – 1).

Therefore, any request for an array element by the index i has to satisfy the condition 0 <= i < array.length, otherwise the ArrayIndexOutOfBoundsException will be thrown.

The following code is a simple example where an ArrayIndexOutOfBoundsException is thrown.

String[] people = new String[] { "Carol", "Andy" };
// An array will be created:
// people[0]: "Carol"
// people[1]: "Andy"
// Notice: no item on index 2. Trying to access it triggers the exception:
System.out.println(people[2]); // throws an ArrayIndexOutOfBoundsException.

Output:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at your.package.path.method(YourClass.java:15)

Note: that the illegal index that is being accessed is also included in the exception (2 in the example); this information could be useful to find the cause of the exception.

To avoid this, simply check that the index is within the limits of the array:

int index = 2;
if (index >= 0 && index < people.length) {
      System.out.println(people[index]);
}

Leave a Comment