Introduction

Arrays are collections of values. Whereas a regular variable can only hold one value at a time, an array can hold multiple values. As a comparison, this is what a regular int variable looks like:

int x = 10;

And this is what an int array looks like:

int[] x = {7, 356, 29, 107, 480};

Whereas x in the first example contains only one value (10), x in the second example contains five values (7, 256, 29, 107, 480). The square brackets ([]) after the data type is how you declare an array variable instead of a normal one. The curly brackets ({}) contain the values to be stored in the array, separated by commas. Values in arrays are called elements and an array can hold as few or as many elements as needed. The number of elements an array contains is called the array’s length or size (once an array is created, its size cannot be changed). Every element in an array is numbered sequentially, starting at 0. This is called the index number. The figure below shows how you can imagine array x.

Indexes and values in array x

You access elements via their index number in square brackets. For example, x[2] means “index 2 of array x”, which is 29. This is what it looks like in a program:

public class Arrays1 {
    public static void main(String[] args) {
       int[] x = {7, 319, 29, 107, 480};
       System.out.println(x[2]);
    }
}
[Run]
29

Line 3 creates an int array called x. It contains the five elements from above. Line 4 prints x[2] (29).

In general, we can do with array elements what can be done with regular variables. See if you can follow the program below.

public class Arrays2 {
    public static void main(String[] args) {
       int[] x = {7, 319, 29, 107, 480};
       System.out.println(x[3]);
       x[3] = 89;
       int a = x[0];
       System.out.print(a + x[4] - x[3]);
    }
}
[Run]
107
398

Line 3 is the same as before. Line 4 prints index 3 (107). On line 5, index 3 is reassigned (107 is overwritten by 89). Line 6 copies index 0 into variable a (x[0] is 7 so a is also 7). Line 7 calculates and prints a + x[4] – x[3], which is 7 + 480 – 89, resulting in 398.

What happens if you try accessing an index that doesn’t exist, like index 5?

public class Arrays3 {
    public static void main(String[] args) {
       int[] x = {7, 319, 29, 107, 480};
       System.out.println(x[5]);
    }
}

In this case you get an “index out of bounds” error:

[Run]
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
at Arrays1.main(Arrays1.java:4)

Array Types

You can create arrays of any data type. The figure below shows Regular variables and their Array counterparts, both with arbitrary values.

TypeRegularArray
intint v = 17;int[] v = {17, -38, 0, 1096, 525, 17, -811, 50}
doubledouble w = 23.50;double[] w = {18.3, 0.831, 272.63, -8.9};
charchar x = ‘>’;char[] x = {‘#’, ‘>’, ‘*’, ‘K’, ‘+’, ‘3’};
booleanboolean y = true;boolean[] y = {false, true, true, false, true}
StringString z = “Hello”;String[] z = {“Cup of Java”, “Howdy”, “vj49gt$”};
Regular variables and array variables.

As you can see, arrays can hold multiple values of their respective type. All arrays use the same indexing scheme starting at 0. For example, in row five, the String array z holds three strings, and the code z[1] refers to the string “Howdy”. The arrays are created using an initialiser list. That is, values between curly brackets ({}). Conversely, the figure below shows how to create the same type of arrays the classic way. The Array Definition column shows how to create arrays of different types using the new keyword. For example, in row 1, the code new int[5] creates an int array with 5 elements. Like previous examples, the array is stored in a variable (v). This variable’s type is int[] meaning it can hold an int array. The Default Values column shows what the array actually looks like when created in this way. Every element is given a default value depending on its type.

TypeArray DefinitionDefault Values
intint[] v = new int[5];{0, 0, 0, 0, 0}
doubledouble[] w = new double[5];{0.0, 0.0, 0.0, 0.0, 0.0}
charchar[] x = new char[5];{‘\0’, ‘\0’, ‘\0’, ‘\0’, ‘\0’}
booleanboolean[] y = new boolean[5];{false, false, false, false, false}
StringString[] z = new String[5];{null, null, null, null, null}
Classic array declarations and their default values.

Moving down the rows, we can see that the default value for an int array is 0, a double array is 0.0, a char array is ‘\0’, a boolean array is false, and a String array is null. The value null basically means no data (‘\0’ is the char’s equivalent of null). We’ll look into null a little later.

Looping Through Arrays

Often, we want to perform some action on each element in an array. For example, we may want to print each element. We could do this manually like so:

public class Arrays1 {
    public static void main(String[] args) {
        int[] x = {7, 319, 29, 107, 480};
        System.out.println(x[0]);
        System.out.println(x[1]);
        System.out.println(x[2]);
        System.out.println(x[3]);
        System.out.println(x[4]);
    }
}
[Run]
7
319
29
107
480

Lines 4-8 print out each element individually. But what if we had hundreds or thousands of elements in the array? We certainly don’t want to write thousands of print statements! This is where loops come in. We can write a loop that prints the next index on each iteration. Remember in the previous chapter how we used i in loops to count up or down (0 to 9 for instance). Since array indexes (or indices) are also numbered, we can use i in place of the index number to access every array element automatically. For example:

public class Arrays3 {
    public static void main(String[] args) {
        int[] x = {7, 319, 29, 107, 480};
        for (int i = 0; i < 5; i++) {
            System.out.println(x[i]);
        }
    }
}
[Run]
7
319
29
107
480

This program does the same thing as the previous one but using a loop. Lines 4-6 is a for loop. Line 4 tells us that the loop starts with i at 0 and stops when i is 5. This means i will go through numbers 0, 1, 2, 3, 4. Thus, x[i] (line 5) will give each subsequent element in the array. Just so it’s clear, let’s go through it manually:

  1. Line 3 creates an array of five elements.
  2. Line 4 is the start of the for loop. In it, variable i is declared and set to 0. The condition is checked (i < 5), which is true. Line 5 prints x[i]. Since i is 0, this is the same as x[0], so 7 is printed.
  3. i++ increases i (so i = 1). i < 5 is true. Line 5 prints x[i] (x[1]) so 319 is printed.
  4. i++ increases i (so i = 2). i < 5 is true. Line 5 prints x[i] (x[2]) so 29 is printed.
  5. i++ increases i (so i = 3). i < 5 is true. Line 5 prints x[i] (x[3]) so 107 is printed.
  6. i++ increases i (so i = 4). i < 5 is true. Line 5 prints x[i] (x[4]) so 480 is printed.
  7. i++ increases i (so i = 5). i < 5 is false. The loop ends and so does the program.

The above program works but not only is it inflexible, it’s also brittle. If the array contained more than five elements, we’d have to remember to change the loop condition otherwise not all elements will be printed. Even worse, if the array contained fewer than five elements and we forgot the amend the condition then the program would crash since the loop would go out of bounds of the array. We need a way to tell the loop to repeat the same number of times as the number of elements in the array. This is actually quite easy. Arrays have an internal length variable that keeps track of the number of elements. We can read this variable directly as demonstrated in the following program.

public class Arrays1 {
    public static void main(String[] args) {
        int[] x = {7, 319, 29, 107, 480, 54, 1833};
        for (int i = 0; i < x.length; i++) {
            System.out.println(x[i]);
        }
    }
}

The condition has been changed to i < x.length so the loop will always repeat the appropriate number of times. I’ve added two more elements to x making a total of seven elements. Therefore, the loop condition is basically i < 7, ergo the loop repeats seven times printing indexes 0 to 6.

[Run]
7
319
29
107
480
54
1833

Now in Reverse

Now let’s loop through the array backwards. In order to do so, we need i to start at the last index, decrease by 1 each iteration, and stop when it reaches index 0. For instance:

public class Arrays1 {
    public static void main(String[] args) {
        int[] x = {7, 319, 29, 107, 480, 54, 1833};
        for (int i = x.length - 1; i >= 0; i--) {
            System.out.println(x[i]);
        }
    }
}
[Run]
1833
54
480
107
29
319
7

All three parts of the for loop need to change in order to loop through the array backwards. Let’s look at the first part, int i = x.length – 1. This tells us that i will start at x.length – 1, which is 7 – 1, which is 6 (the last index). Note that an array’s length minus one will always give the last index in an array, of any size. The condition i >= 0 tells us that the loop will repeat as long as i is greater than or equal to 0. The third part i-- will decrease i every iteration so that i goes through 6, 5, 4, 3, 2, 1, 0. It also decreases once more to -1 but this causes the condition to be false, so the loop ends (otherwise line 5 would give an out of bounds error).

Simple Array Processing

Iterating over arrays is very useful in programming because it allows us to write common code for all elements. For example, the program below only prints elements that are greater than 100.

public class GreaterThan100 {
    public static void main(String[] args) {
        int[] x = {7, 319, 29, 107, 480, 54, 1833};
        for (int i = 0; i < x.length; i++) {
            if (x[i] > 100) {
                System.out.println(x[i]);
            }
        }
    }
}
[Run]
319
107
480
1833

As we can see, values 319, 107, 480, and 1833 are printed whereas 7, 29, and 54 are not. This is due to the if statement on line 5 that checks if x[i] is greater than 100 and therefore only prints the number if true. Here is a rundown of the steps the program takes:

  1. Line 4: int i = 0i < x.length is true.
  2. Line 5: x[i] > 100 (7 > 100) is false.
  3. Line 4: i++ (i is 1) → i < x.length is true.
  4. Line 5: x[i] > 100 (319 > 100) is true.
  5. Line 6: Print x[i] (319).
  6. Line 4: i++ (i is 2) → i < x.length is true.
  7. Line 5: x[i] > 100 (29 > 100) is false.
  8. Line 4: i++ (i is 3) → i < x.length is true.
  9. Line 5: x[i] > 100 (107 > 100) is true.
  10. Line 6: Print x[i] (107).
  11. And so on…

If you’re having trouble untangling the program in your head then think about it this way: At this point we can basically ignore the loop because all it does is cause i to go from 0 to 7. So, let’s focus purely on the if statement (line 5). x[i] is going to be x[0] (7), then x[1] (319), then x[2] (29), then x[3] (107), etc. Therefore, the if statement goes through every element in the array to see if it’s greater than 100. If true, it gets printed (line 6); if false, it doesn’t. That’s it, really. Another way to think about it is that x[i] is like a placeholder for each element in the array, where each element is substituted one at a time.

Arrays Are Reference Types

There are two categories of (data) types: primitive types and reference types. Recall that there are only eight primitive types: byte, short, int, long, float, double, char, and boolean. All other types are reference types—these include all the reference types we’ve looked at so far such as String, Scanner, and DecimalFormat, as well as arrays themselves. The key difference between the two types is that variables of primitive types contain their values directly whereas variables of reference types contain their values indirectly. What does this mean in practice? Take the following code:

int a = 5;
int b = a;

First, a is set to 5. Then, b is set to a. This means the value of a gets copied into b i.e. 5 gets copied into b. Both a and b end up being 5. We can picture a and b like this:

Text Box: int[] aArr = {5, 14, 11};
int[] bArr = aArr;
Primitive variables

Let’s now try the same thing with arrays:

int[] c = {5, 14, 11};
int[] d = c;

Array c contains arbitrary values 5, 14, and 11. Underneath, d is set to c. It’s reasonable to think that the array {5, 14, 11} gets copied into d, so both c and d end up being {5, 14, 11}. But this isn’t exactly what happens because array variables do not contain arrays directly. In reality, the array {5, 14, 11} is stored in some memory location and the variable c contains a reference to it (a reference is akin to a memory address). In other words, c contains the location of the array, not the array itself. This means when d is set to c, the reference in c is copied into d so both variables end up referencing the same array. The following figure depicts this:

Reference variables

Again, what c contains is a reference (0x5A41) to the array. When d is set to c, this reference is copied into d. Therefore, both variables end up referencing the same array. This means any changes made to the array in d will be reflected in c and vice versa, because they are one and the same. Let’s look at a program that demonstrates this:

public class ArrayReference {
    public static void main(String[] args) {
        int[] c = {5, 14, 11};
        int[] d = c;

        d[1] = 75;

        System.out.println(Arrays.toString(c));
        System.out.println(Arrays.toString(d));
    }
}
[Run]
[5, 75, 11]
[5, 75, 11]

Lines 3 and 4 recreate the two arrays from the example. Then, line 6 changes index 1 in d to 75 (originally 14). Lines 8 and 9 print out the contents of both arrays. As we can see from the output, both c and d show 75 even though it was only d that was altered on line 6. Again, it’s because there’s only one array and both c and d hold a reference to it, so a change to one is a change to the other. And, by the way, for printing the two arrays on lines 8 and 9, I used a handy method from the Arrays class called toString. This method takes an array and returns a human-readable string of its contents i.e. “[5, 75, 11]”. This saves us from having to manually loop through both arrays just to print out their elements.

Multidimensional Arrays

Multidimensional arrays are arrays of more than 1 dimension. So far, we’ve only looked at 1-dimensional (1D) arrays, which can be thought of as a sequence of values.

Two-dimensional Array

A 2-dimensional array is defined by using two pairs of square brackets:

int[][] a2d = new int[4][5];

a2d is a 4 by 5 array. 2D arrays can be imagined as a grid of values with rows and columns. By default, all values are 0 so a2d looks like this:

A 2D (4×5) array portrayed as a grid.

2D arrays aren’t that much more complicated than 1D arrays, we just need to remember that we’re dealing with a 2D grid and not a 1D line, thus we need two pairs of square brackets instead of one. For example, the following line changes the element at [3][1] to 5:

a2d[3][1] = 5;
The affected element.

We can also think of 2D arrays as an array of arrays (of values). We get a good visualisation of this by creating the same 4 x 5 array using an initialiser list:

int[][] a2d = { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} };

a2d contains 4 arrays. Each array itself contains 5 values (all zeros). If this is unclear, here is each array highlighted:

int[][] a2d = { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} };

Let’s change the element at [2][2] to a different value:

a2d[2][2] = 91;

The first [2] specifies an array. The second [2] specifies a value in that array. Now a2d looks like this:

a2d { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 91, 0, 0}, {0, 0, 0, 0, 0} };

Remember that array indexing starts at 0 so [2][2] really means the 3rd value of the 3rd array, as illustrated in the following figure:

Text Box: a2d[0][3] = -23;

How about changing the element at [0][3]:

a2d[0][3] = -23;
a2d { {0, 0, 0, -23, 0}, {0, 0, 0, 0, 0}, {0, 0, 91, 0, 0}, {0, 0, 0, 0, 0} };
Text Box: a2d { {0, 0, 0, -23, 0}, {0, 0, 0, 0, 0}, {0, 0, 91, 0, 0}, {0, 0, 0, 0, 0} };

Three-dimensional Arrays

Arrays can be of any number of dimensions—3D, 4D, 5D, 10D, etc. The more dimensions, the more square brackets. A 3D array is defined with 3 pairs of square brackets:

int[][][] a3d = new int[2][4][3];

And this is the same array created using an initialiser list:

int[][][] a3d = { { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }, { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} } };

You can imagine a 3D array as a cube of values, whereby you go along the x, y, and z axes. Or you can imagine it as an array of arrays of arrays of values (yikes). This isn’t so bad if we break it down like before by highlighting each part.

This is the whole array:

{ { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }, { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} } }

Inside are [2] arrays:

{ { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }, { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} } }

Inside are [4] arrays each:

{ { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }, { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} } }

Inside are [3] values each:

{ { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }, { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} } }

Therefore element [1][0][2], for example, refers to the element coloured in red:

{ { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }, { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} } }

Foreach Loop

A foreach loop can be used in place of a for loop when you want to loop through an array. A foreach loop simplifies the syntax and can make code easier to read. As an example, the following program uses a classic for loop to output the contents of an array.

public class ClassicForLoop {
    public static void main(String[] args) {
        double[] someArray = {25.92, 1.34, -76.24, 833.11, 76.084};

        for (int i = 0; i < someArray.length; i++) {
            System.out.println(someArray[i]);
        }
    }
}
[Run]
25.92
1.34
-76.24
833.11
76.084

Line 3 creates an array called someArray, which contains five elements. The for loop underneath iterates over (loops through) the array, where line 6 simply prints out each element.

Now let’s do the same thing but with a foreach loop:

public class ForEachLoop {
    public static void main(String[] args) {
        double[] someArray = {25.92, 1.34, -76.24, 833.11, 76.084};

        for (double e : someArray) {
            System.out.println(e);
        }
    }
}

Here, someArray is the array to iterate over and e is each element in the array. A colon separates the two. You can read it as “For each e (element) in someArray, do whatever’s in the body”. To elaborate, e is simply a variable. Every time the loop repeats, e will contain the next element from someArray. So, on the first iteration, e is 25.92, the second iteration e is 1.34, the third iteration e is -76.24, and so on, until the end. On each iteration, e is printed on line 6. A foreach loop always repeats the same number of times as the number of elements in the array, so you don’t have to worry about it going out of bounds. Furthermore, e is a double because that’s what the arrays contains, a set of doubles. If someArray were a String array, you would have to make e a String variable to hold each element. Also, you don’t have to call it e, you can call it anything you like, with it being a variable and all.

Leave a Reply

Your email address will not be published. Required fields are marked *