Arrays Revisted#

Arrays are a built-in structured data type in Java that allows access to multiple items under one name. The word “structured” means putting multiple data together in one unit. You can think of arrays as a container, holding from zero to many pieces of information. With arrays, that information lies in the computer’s memory in contiguous cells and each item of data must be of the same data type. We call this homogeneous data. Technically arrays are a reference data type and this means that the name for an array stores an address in memory that points to the actual data. Here is a visualization of an array called x that contains seven items:

x pointing to address cell which points to array

Because all reference data types use the extra memory cell to hold the address, it is simpler to omit that cell in our drawings and still have an adequate visualization of the process. A normal drawing of an array is:

x pointing to array

Arrays are declared by using the data type of the items you want to store in the array and adding square brackets [], along with the array’s name. Here are examples of some simple array declarations:

  1. An array of integers: int[] favNums;

  2. An array of strings: String[] libraryBooks;

  3. An array of double precision floating point values: double[] earnings;

None of the above arrays (favNums, libraryBooks, earnings) contain any values yet, nor are they accessible. They have not been created in memory. There are two ways to create or initialize arrays.

  1. If you know all the initial values, just use a direct assignment, for example:

    int[] favNums = {1, 2, 89, 5, 12};
    

    will make an array of five integers in memory with the values given.

    favNums pointing to array with elements 1, 2, 89, 5, 12

  1. Assigning the values during run-time. When you know the size of the array, create the array using Java’s new reserved word and put the size in square brackets. The size can come from a variable, but once the array has been made, its size will never change. Here is an example, assuming numberEarnings contains an integer:

    double[] earnings;
    
    //And then once we know how big to make the array:
    earnings = new double[numberEarnings];
    

    If you know the size of the array right at the beginning, then you could create the array along with the declaration. For example,

    double[] earnings = new double[20];
    

    creates an array with 20 floating point numbers, all initialized to 0.0.

    earnings pointing to 20 cells, which are all 0.0

    Java will initialize parts of structures to 0 (or the equivalent depending on the data type); Java does not initialize primitive unstructured data.

Arrays are a strange beast, crossing the line somewhat between tradition and OOPs where all objects are made with new followed by a call to a constructor. Be very careful. When arrays are made with the new reserved word, they are created dynamically, but need their size parameter in [], which is not the usual constructor invocation where () is expected.

Regardless of how arrays were created, they are mutable, meaning that their values may change at run-time. Any value may be changed by using an assignment to the name with an index, as long as the index is valid. Here is an example of changing the 2nd item of favNums to 91: favNums[1] = 91;

favNums pointing to array with elements 1, 91, 89, 5, 12

All indices must be zero or positive integers (no negative integers, as in Python). Zero is always the first index. We will later see data types that can hold information of different kinds and sizes and that are accessed in different ways than indexing by a number. Do not confuse arrays with ArrayLists, which we will learn about later.



Array Index with Non-Negative Integers, Starting at 0

When we come from other programming languages this won’t be obvious. Some languages start indexing at 1 (this might even be what our intuition tells us to do). Some languages allow negative indices to move from the back of the array. In Java, the last index is the array’s length minus 1.



Printing an Array#

We are going to want to print out arrays. Let’s try it:

int[] favNums = {1, 2, 89, 5, 12};
System.out.println(favNums);
[I@21d344ca

When we run the program we see something like this (results may vary): [I@245afba3 This is essentially a memory address (a few lead characters and then hexadecimal, but this may vary, depending on your computer and your operating system). This is not as expected! Since an array is a reference data type, it will print as an address (recall that the array’s name really directs to a memory cell that contains an address). All reference data types print as addresses (unless the toString method has been overwritten, as we will see in the next chapter). If individual parts of a structure are to be printed, e.g. as in each item, then that must be coded explicitly. It is natural to use a for-each loop with an array.

int[] favNums = {1, 2, 89, 5, 12};
for(int oneNumber : favNums){
   System.out.print(oneNumber + " ");
}
System.out.println();
1 2 89 5 12 

When working with arrays you would be printing a lot. So it’s a great idea to make yourself a method to print them. For example, a method to print any integer array:

/**
 * Displays values in 1d array of integers on single line
 * of standard output.
 * @param intArray is a 1d array of integers
 */
 public static void printIntArray(int[] intArray){
    for(int oneNumber : intArray){
       System.out.print(oneNumber + " ");
    }
       System.out.println();
 }

Now you can print the values inside the favNums array as follows:

printIntArray(favNums);
1 2 89 5 12 

While we are at it we can also easily print any other one-dimensional array of integers. This is a clear illustration of the power of methods and the reuse of code. For example,

int[] numbers2 = {100, 12, 3089, 112};
printIntArray(numbers2);
100 12 3089 112 

There are many common operations on arrays, including printing them. Java contains an Arrays library which may be imported for that purpose.

import java.util.Arrays;

However, when learning Java, we will rarely be using that library, so that we develop a better understanding of how loops and structures work.

Equality of Arrays#

Here is a small Java program. Can you predict the output without running it on a machine?

int[] favNums = {1, 2, 89, 5, 12};
int[] bobNums = {1, 2, 89, 7, 12};
bobNums[3] = 5;
      
if (bobNums == favNums){
   System.out.println("The are the SAME");
}
else{
   System.out.println("NO NO NO");
}
Hide code cell output
NO NO NO

It might be a surprise to see that the output is actually the “NO” series. Why is that? The two arrays certainly contain the same values. If you recall, though, arrays are stored as an address of where they are located. Thus, == simply verifies whether those addresses are the same. It never checks individual values.

Suppose we modify our code slightly:

int[] favNums = {1, 2, 89, 5, 12};
int[] bobNums = favNums; //See here, we made them the same
bobNums[3] = 40;
      
if (bobNums == favNums){
   System.out.println("They are the SAME");
}
else{
   System.out.println("NO NO NO"); 
}
Hide code cell output
They are the SAME

Now bobNums contains the same address as favNums, and so this program will print “They are the SAME”. The change made to bobNums is also a change made to favNums. This is called aliasing: two names for the same memory location. Aliasing makes codes very hard to read and should be avoided.

We could write a Java function to compare two arrays, at the value level, that is our function should return true if and only if all the values match. Our first check would need to make sure that the lengths are the same and then we create a loop to traverse each array simultaneously and we check corresponding values. Here is one way to do this for two arrays of integers:

/**
 * Returns true if the two parameters (both 1d arrays of integers)     
 * contain the same values; returns false otherwise.
 *
 * @param array1 is a 1d array of integers
 * @param array2 is a 1d array of integers
 * @return true if the arrays contain the same items; false otherwise
 */
 public static boolean equalsIntArray(int[] array1, int[] array2){
    //sizes of arrays must match
    if (array1.length != array2.length){
       return false;
    }

	//compare value to value
    int index = 0;
    while (index < array1.length){
       if (array1[index] != array2[index]){//found mismatch
          return false;
       }
       index++;
     }//while  
 
     return true; //if we made it all the way, values are all the same
 }//equalsIntArray

Practice Questions#

  1. Given the following Java code:

    int[] y = {15, 85, 32, 4, 17, 76, 48, 2, 90, 73, 7, 18, 9};
    

    a. How would you access the 85?
    b. How would you access the 9?
    c. How would you access the 48?

  2. Make your name as an array of characters (not as a String). Then print out this array to show your name.

  3. Write a method that takes a 1D array of integers and a particular integer and returns an array of integers with all the indices where the particular integer occurred. If the integer is absent from the array, return null. [Hint: Make two passes through the array, first counting how many occurrences and second placing the indices into the new array.]

To Solutions