Stats

Contributors: 168 Tuesday, July 4, 2017
Licensed under: CC-BY-SA
Not affiliated with Stack Overflow
Rip Tutorial: riptutorial@gmail.com
Roadmap: roadmap

Creating and Initializing Arrays

Example

Basic cases

int[]   numbers1 = new int[3];                 // Array for 3 int values, default value is 0
int[]   numbers2 = { 1, 2, 3 };                // Array literal of 3 int values
int[]   numbers3 = new int[] { 1, 2, 3 };      // Array of 3 int values initialized
int[][] numbers4 = { { 1, 2 }, { 3, 4, 5 } };  // Jagged array literal
int[][] numbers5 = new int[5][];               // Jagged array, one dimension 5 long
int[][] numbers6 = new int[5][4];              // Multidimensional array: 5x4

Arrays may be created using any primitive or reference type.

float[]  boats = new float[5];          // Array of five 32-bit floating point numbers.
double[] header = new double[] { 4.56, 332.267, 7.0, 0.3367, 10.0 };
                                       // Array of five 64-bit floating point numbers.
String[] theory = new String[] { "a", "b", "c" };
                                       // Array of three strings (reference type).
Object[] dArt = new Object[] { new Object(), "We love Stack Overflow.", new Integer(3) };
                                       // Array of three Objects (reference type).

For the last example, note that subtypes of the declared array type are allowed in the array.

Arrays for user defined types can also be built similar to primitive types

UserDefinedClass[] udType = new UserDefinedClass[5];

Arrays, Collections, and Streams

Java SE 1.2
// Parameters require objects, not primitives

// Auto-boxing happening for int 127 here
Integer[]       initial        = { 127, Integer.valueOf( 42 ) };
List<Integer>   toList         = Arrays.asList( initial );  // Fixed size! 

// Note: Works with all collections
Integer[]       fromCollection = toList.toArray( new Integer[toList.size()] );

//Java doesn't allow you to create an array of a parameterized type
List<String>[]  list = new ArrayList<String>[2];  // Compilation error!
Java SE 8
// Streams - JDK 8+
Stream<Integer> toStream       = Arrays.stream( initial );
Integer[]       fromStream     = toStream.toArray( Integer[]::new );

Intro

An array is a data structure that holds a fixed number of primitive values or references to object instances.

Each item in an array is called an element, and each element is accessed by its numerical index. The length of an array is established when the array is created:

int size = 42;
int[] array = new int[size];

The size of an array is fixed at runtime when initialized. It cannot be changed after initialization. If the size must be mutable at runtime, a Collection class such as ArrayList should be used instead. ArrayList stores elements in an array and supports resizing by allocating a new array and copying elements from the old array.

If the array is of a primitive type, i.e.

int[] array1 = { 1,2,3 };
int[] array2 = new int[10];

the values are stored in the array itself. In the absence of an initializer (as in array2 above), the default value assigned to each element is 0 (zero).

If the array type is an object reference, as in

SomeClassOrInterface[] array = new SomeClassOrInterface[10];

then the array contains references to objects of type SomeClassOrInterface. Those references can refer to an instance of SomeClassOrInterface or any subclass (for classes) or implementing class (for interfaces) of SomeClassOrInterface. If the array declaration has no initializer then the default value of null is assigned to each element.

Because all arrays are int-indexed, the size of an array must be specified by an int. The size of the array cannot be specified as a long:

long size = 23L;
int[] array = new int[size]; // Compile-time error:
                             // incompatible types: possible lossy conversion from
                             // long to int

Arrays use a zero-based index system, which means indexing starts at 0 and ends at length - 1.

For example, the following image represents an array with size 10. Here, the first element is at index 0 and the last element is at index 9, instead of the first element being at index 1 and the last element at index 10 (see figure below).

An array of 10 elements

Accesses to elements of arrays are done in constant time. That means accessing to the first element of the array has the same cost (in time) of accessing the second element, the third element and so on.

Java offers several ways of defining and initializing arrays, including literal and constructor notations. When declaring arrays using the new Type[length] constructor, each element will be initialized with the following default values:

Creating and initializing primitive type arrays

int[] array1 = new int[] { 1, 2, 3 }; // Create an array with new operator and 
                                      // array initializer.
int[] array2 = { 1, 2, 3 };           // Shortcut syntax with array initializer.
int[] array3 = new int[3];            // Equivalent to { 0, 0, 0 }
int[] array4 = null;                  // The array itself is an object, so it
                                      // can be set as null.

When declaring an array, [] will appear as part of the type at the beginning of the declaration (after the type name), or as part of the declarator for a particular variable (after variable name), or both:

int array5[];       /* equivalent to */  int[] array5;
int a, b[], c[][];  /* equivalent to */  int a; int[] b; int[][] c;
int[] a, b[];       /* equivalent to */  int[] a; int[][] b;
int a, []b, c[][];  /* Compilation Error, because [] is not part of the type at beginning
                       of the declaration, rather it is before 'b'. */    
// The same rules apply when declaring a method that returns an array:
int foo()[] { ... } /* equivalent to */  int[] foo() { ... }

In the following example, both declarations are correct and can compile and run without any problems. However, both the Java Coding Convention and the Google Java Style Guide discourage the form with brackets after the variable name—the brackets identify the array type and should appear with the type designation. The same should be used for method return signatures.

float array[]; /* and */ int foo()[] { ... } /* are discouraged */
float[] array; /* and */ int[] foo() { ... } /* are encouraged */

The discouraged type is meant to accommodate transitioning C users, who are familiar with the syntax for C which has the brackets after the variable name.

In Java, it is possible to have arrays of size 0:

int[] array = new int[0]; // Compiles and runs fine.
int[] array2 = {};        // Equivalent syntax.

However, since it's an empty array, no elements can be read from it or assigned to it:

array[0] = 1;     // Throws java.lang.ArrayIndexOutOfBoundsException.
int i = array2[0]; // Also throws ArrayIndexOutOfBoundsException.

Such empty arrays are typically useful as return values, so that the calling code only has to worry about dealing with an array, rather than a potential null value that may lead to a NullPointerException.

The length of an array must be a non-negative integer:

int[] array = new int[-1]; // Throws java.lang.NegativeArraySizeException

The array size can be determined using a public final field called length:

System.out.println(array.length); // Prints 0 in this case.

Note: array.length returns the actual size of the array and not the number of array elements which were assigned a value, unlike ArrayList.size() which returns the number of array elements which were assigned a value.

Creating and initializing multi-dimensional arrays

The simplest way to create a multi-dimensional array is as follows:

int[][] a = new int[2][3];

It will create two three-length int arrays—a[0] and a[1]. This is very similar to the classical, C-style initialization of rectangular multi-dimensional arrays.

You can create and initialize at the same time:

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

Unlike C, where only rectangular multi-dimensional arrays are supported, inner arrays do not need to be of the same length, or even defined:

int[][] a = { {1}, {2, 3}, null };

Here, a[0] is a one-length int array, whereas a[1] is a two-length int array and a[2] is null. Arrays like this are called jagged arrays or ragged arrays, that is, they are arrays of arrays. Multi-dimensional arrays in Java are implemented as arrays of arrays, i.e. array[i][j][k] is equivalent to ((array[i])[j])[k]. Unlike C#, the syntax array[i,j] is not supported in Java.

Multidimensional array representation in Java

Visual representation of a Java multidimensional array

Source - Live on Ideone

Creating and initializing reference type arrays

String[] array6 = new String[] { "Laurel", "Hardy" }; // Create an array with new 
                                                      // operator and array initializer.
String[] array7 = { "Laurel", "Hardy" };              // Shortcut syntax with array 
                                                      // initializer.
String[] array8 = new String[3];                      // { null, null, null }
String[] array9 = null;                               // null

Live on Ideone

In addition to the String literals and primitives shown above, the shortcut syntax for array initialization also works with canonical Object types:

Object[] array10 = { new Object(), new Object() };

Because arrays are covariant, a reference type array can be initialized as an array of a subclass, although an ArrayStoreException will be thrown if you try to set an element to something other than a String:

Object[] array11 = new String[] { "foo", "bar", "baz" };
array11[1] = "qux"; // fine
array11[1] = new StringBuilder(); // throws ArrayStoreException

The shortcut syntax cannot be used for this because the shortcut syntax would have an implicit type of Object[].

An array can be initialized with zero elements by using String[] emptyArray = new String[0]. For example, an array with zero length like this is used for Creating an Array from a Collection when the method needs the runtime type of an object.

In both primitive and reference types, an empty array initialization (for example String[] array8 = new String[3]) will initialize the array with the default value for each data type.

Creating and initializing generic type arrays

In generic classes, arrays of generic types cannot be initialized like this due to type erasure:

public class MyGenericClass<T> {
    private T[] a;

    public MyGenericClass() {
        a = new T[5]; // Compile time error: generic array creation
    }
}

Instead, they can be created using one of the following methods: (note that these will generate unchecked warnings)

  1. By creating an Object array, and casting it to the generic type:

    a = (T[]) new Object[5];
    

    This is the simplest method, but since the underlying array is still of type Object[], this method does not provide type safety. Therefore, this method of creating an array is best used only within the generic class - not exposed publicly.

  2. By using Array.newInstance with a class parameter:

    public MyGenericClass(Class<T> clazz) {
        a = (T[]) Array.newInstance(clazz, 5);
    }
    

    Here the class of T has to be explicitly passed to the constructor. The return type of Array.newInstance is always Object. However, this method is safer because the newly created array is always of type T[], and therefore can be safely externalized.

Filling an array after initialization

Java SE 1.2

Arrays.fill() can be used to fill an array with the same value after initialization:

Arrays.fill(array8, "abc");        // { "abc", "abc", "abc" }

Live on Ideone

fill() can also assign a value to each element of the specified range of the array:

Arrays.fill(array8, 1, 2, "aaa");  // Placing "aaa" from index 1 to 2.

Live on Ideone

Java SE 8

Since Java version 8, the method setAll, and its Concurrent equivalent parallelSetAll, can be used to set every element of an array to generated values. These methods are passed a generator function which accepts an index and returns the desired value for that position.

The following example creates an integer array and sets all of its elements to their respective index value:

int[] array = new int[5];
Arrays.setAll(array, i -> i); // The array becomes { 0, 1, 2, 3, 4 }.

Live on Ideone

Separate declaration and initialization of arrays

The value of an index for an array element must be a whole number (0, 1, 2, 3, 4, ...) and less than the length of the array (indexes are zero-based). Otherwise, an ArrayIndexOutOfBoundsException will be thrown:

int[] array9;             // Array declaration - uninitialized
array9 = new int[3];      // Initialize array  - { 0, 0, 0 }
array9[0] = 10;           // Set index 0 value - { 10, 0, 0 }
array9[1] = 20;           // Set index 1 value - { 10, 20, 0 }
array9[2] = 30;           // Set index 2 value - { 10, 20, 30 }

Arrays may not be re-initialized with array initializer shortcut syntax

It is not possible to re-initialize an array via a shortcut syntax with an array initializer since an array initializer can only be specified in a field declaration or local variable declaration, or as a part of an array creation expression.

However, it is possible to create a new array and assign it to the variable being used to reference the old array. While this results in the array referenced by that variable being re-initialized, the variable contents are a completely new array. To do this, the new operator can be used with an array initializer and assigned to the array variable:

// First initialization of array
int[] array = new int[] { 1, 2, 3 };

// Prints "1 2 3 ".
for (int i : array) {
    System.out.print(i + " ");
}

// Re-initializes array to a new int[] array.
array = new int[] { 4, 5, 6 };

// Prints "4 5 6 ".
for (int i : array) {
    System.out.print(i + " ");
}

array = { 1, 2, 3, 4 }; // Compile-time error! Can't re-initialize an array via shortcut 
                        // syntax with array initializer.

Live on Ideone