Skip to main content
Logo image

Section 6.1 Creating and using arrays

Suppose we were writing a program to deal with students’ exam scores. To keep track of ten exam scores, we could declare ten separate variables: int score1, score2, score3, … , score10. But what if we had a hundred exam scores? That would be a lot of variables! Worse yet, what if we didn’t know when we were writing the program how many scores we would need to deal with?
What we would like is some way to declare, β€œI’m going to need to store n int values” where n is a number that isn’t necessarily known until the program runs. And we might also like to be able to treat that collection of n values as a single value for some purposesβ€”being able to assign it to a variable or pass it as an argument to a methodβ€”while still being able to access the individual values. Even better would be if this new kind of value knew how many values were in it so we could do things like write loops that access each of the component values no matter how many there are.
In Java that’s what arrays are for. Most programming languages have some similar kind of data structure, usually called arrays or lists. The basic idea is that we have a single value that stores a collection of values called the elements of the array and then allows us to access the individual elements by a number, rather than a name. So instead of a bunch of variables with names like score1 and score2, we can have one variable named scores and access the elements like scores[0] and scores[1]. Anything we can do with a regular variable, such as using it in an expression or assigning it a value we can also do with an array element.
An array is like a row of lockers, except that you can’t cram lots of stuff into each locker; each locker only holds one thing.
Figure 6.1.1. A row of lockers
We can access the elements of an array using an index, a number that identifies a position in the array, similar to how the number on a locker identifies it out of all the lockers in a hallway. We can use an index to both access and assign te value at that position in an array.
In Java, the object data of arrays is stored in the computer’s memory as contiguous block and the index indicates how far each element is from the front of the block. So the first index is 0, not 1. Most programming languages these days use this kind of zero-based indices but a few, including many block-based languages such as Snap!, use one-based indices where the first item in a list is at index 1. One-based indices fit better with how English speakers number things so if you are coming from Snap! or if Java is your first programming langauge, it may take a little while to remember that the first element of an array is at index 0. (Sometimes programmers will refer to the first element of an array as the β€œzeroth” element to be super clear. Or maybe just because β€œzeroth” is kind of fun to say.)
Here’s a short video that introduces the concept of an array.

Activity 6.1.1. Other analogies?

Can you think of another example of something that is like an array (like a row of lockers)?

Subsection 6.1.1 Declaring array variables

As we’ve already learned, when we declare a variable, we specify its type and name. Declaring an array variable is no different except we need to declare it with an array type. Array types are written with the element type of the array, followed by square brackets. For example to make an array of int values, we use the type int[] which is pronounced β€œarray of int” or β€œint array”.
So as we know, if we want to declare an int variable we write:
int score; // One int value
So if we want to declare an array of int, we write:
int[] scores; // A reference to an array of any number of int values
Because arrays are reference types, when we declare an array variable, the only memory that is allocated is a place to hold a reference to an array. Declaring the variable doesn’t actually create the array object. But what is stored in the variable if there’s no object to reference? Java has a special value null which is the reference equivalent of 0 for an int or 0.0 for a double which means, β€œno object”. Any variable with a reference type that hasn’t been assigned an actual reference value will have the value null.
So before we can use the array variable we need to actually create an array.

Subsection 6.1.2 Creating arrays

The main way to create an actual array object is with an array creation expression. There are two flavors: one that makes an array of a given size where all the elements are 0, 0.0, false, or null depending on the element type and another that lets us specify specific values that will be put into the new array.
To create an array of a specific size we use the keyword new followed by what looks like an array type but with an int expression (often a literal int) inside the square brackets that says how big the array should be. The whole expression causes a new array’s to be created and space allocated for it’s object data and then evaluates to a reference to that new array. We then need to do something with that reference like assign it to a variable or possibly pass it a method.
The following two lines consist of a variable declaration where we immediately assign the variable a reference to a new array.
int[] nums = new int[10]; // a reference to a new array of ten ints
String[] strings = new String[1000000]; // a reference to a new array of a million Strings.
Note that the number only goes in the square brackets in the array creation expression. The size of the array is not part of the type of the variable; it’s just a fact about that particular object. We could later assign a new values to those variables, replacing the original arrays, potentially with new arrays of different sizes.
// clobber the old references
nums = new int[10]; // reference to new array of same size
strings = new String[10]; // reference to new array of different size
When we create an array like this all the values in the new array are initialized to the β€œzero” value for the element type.
  • 0 for elements of type int
  • 0.0 for elements of type double
  • false for elements of type boolean
  • null for all reference types
Figure 6.1.2. Two five-element arrays with their values set to the default values for integer and object arrays.
The other way to make an array, is with specific values using an array initializer sometimes called an initializer list. We still use new but instead of specifying the size of the array inside the square brackets, we place a list of initial values in curly braces ({}) after the square brackets:
int[] highScores = new int[] { 99, 98, 98, 88, 68 };
String[] names = new String[] { "Jamal", "Emily", "Destiny", "Mateo", "Sofia" };
Notice that in this case we don’t need to specify the size of the arrays because Java can figure it out from how many values are in the curly braces.
When we create an array of a primitive type such as int with initial values specified, space is allocated for the specified number of items of that type and the values in the array are stored directly in the array’s object data. When we create an array of an reference type such as String, space is allocated to hold the references in the array. The actual object dataβ€”String objects in this caseβ€”live somewhere else in memory and only references are stored in the array.
Figure 6.1.3. A primitive array and an object array
Finally there’s a shortcut for when we’re declaring a variable and initializing it with specific values at the same time: we can write just the initial values in curly braces without the new and the array type since Java can infer the type from the variable declaration.
int[] highScores = { 99, 98, 98, 88, 68 };
String[] names = { "Jamal", "Emily", "Destiny", "Mateo", "Sofia" };
This is handy but it only works when it is part of a variable declaration. In particular, we can’t use it if we want to pass a reference to a new array as the argument to a method. In that case we need to use a full array creation expression:
someMethod(new int[] { 1, 2, 3 });
Watch the following video which shows the two ways of creating an array with a physical model of Java memory.

Activity 6.1.2.

Which of the following creates an array of 10 doubles called prices?
  • int[] prices = new int[10];
  • We need double for money amounts in prices.
  • double[] prices = new double[10];
  • Yes correct!
  • double[] prices;
  • This declares the array but does not create it with new.
  • double[10] prices = new double[];
  • This is not the correct syntax.

Activity 6.1.3.

In the following code, add another two more array declarations, one that creates an array of 5 doubles called prices and another of 5 Strings called names. Then add System.out.println calls to print their lengths.
Watch the following video which shows an array of String objects with a physical model of Java memory.

Subsection 6.1.3 Array length

The good news about Java arrays is that they know how many elements they can store. The slightly bad news is that there is no way to change that size after the array is created.
The size of each array is stored as part of its object data and is accessible via an instance variable length. We’ll learn more about instance variables in ChapterΒ 8Β Classes but for now all we need to know is that we can access the size of any array with the dot operator, a dot . followed by the word length immediately after any expression whose value is an array reference. For example, arrayName.length accesses the length of the array referenced by the variable arrayName.

Activity 6.1.4.

Try running the code below to see the length. Try adding another value to the highScores initializer list and run again to see the length value change.

Subsection 6.1.4 Accessing and assigning array values

To access the items in an array, we use an array access expression which is a reference to an array (such as the name of an array variable) followed by a pair of square brackets containing an int expression that gives us the index of the element we want to access. Remember that an index is a number that indicates the position of an item in a list, starting at 0.
An array access expression like arrayname[index] can be used anywhere a regular variable can be used. That is, we can use it in an expression to get the value of an element of the array. But we can also use it on the left side of an assignment operator to change the value stored at that position in the array.
System.out.println(highScores[0]); // Print the zeroth element of the array
highScores[0] = 99;                // Assign a new value to the zeroth element of the array
System.out.println(highScores[0]); // Print the zeroth element of the array, now 99
highScores[0] += 5;                // Add five to the value, raising it to 104
highScores[0]++;                   // Increment the value so it's now 105
When accessing array elements, either to get their value or to assign to them, the index must be valid given the size of the array. If not Java will crash your program with an ArrayIndexOutOfBoundsException.
Since the first element is at index 0 that means the last valid index is one less than the length of the array. (An egg carton contains twelve eggs but if you numbered the eggs, starting at 0 the last one would be number 11.)
Watch the following video which shows a physical model of Java memory setting array values.

Activity 6.1.5.

Which index is for the last element of an array called highScores?
  • highScores.length
  • Remember that the first element in an array starts at index 0. If the length (the number of elements) of the array is 5, at what index would you find the last element?
  • highScores.length - 1
  • Since the first element in an array is at index 0 the last element is the length minus 1.

Activity 6.1.6.

Which code below accesses "Honda" using the following array: String[] cars = {β€œHonda”, β€œVolvo”, β€œBMW”};
  • cars[0]
  • Yes, this would access "Honda". Remember that the first element in an array starts at index 0.
  • cars[1]
  • No, this would access "Volvo". Remember that the first element in an array starts at index 0.
  • cars[2]
  • No, this would access "BMW". Remember that the first element in an array starts at index 0.
  • cars[3]
  • No, this would result in an IndexOutOfBounds error. Remember that the first element in an array starts at index 0.

Activity 6.1.7.

Which code below accesses "BMW" in the array: String[] cars = {β€œHonda”, β€œVolvo”, β€œBMW”};
  • cars[0]
  • No, this would access "Honda". Remember that the first element in an array starts at index 0.
  • cars[1]
  • No, this would access "Volvo". Remember that the first element in an array starts at index 0.
  • cars[2]
  • Yes, this would access "BMW". If there are n elements and you start indexing at 0, the last element is at index n-1.
  • cars[3]
  • No, this would result in an IndexOutOfBounds error. Remember that the first element in an array starts at index 0.
If you want to keep track of the top five highest scores in a game and the names of the people with those scores, you could use two parallel arrays. One array could keep track of the scores and the other the names. You have to make sure you keep them in the same order so that the same index can be used to get correponding names and scores.

Activity 6.1.8.

Try out the following code which has two parallel arrays, highScores and names. Can you print out Mateo’s score? Can you change Sofia’s score to 97 using an assignment statement in the code? Can you change the arrays so that they have 6 elements and add your name and score and print them out?
What happens if you try to access an element that is not there? Try to access a highScore or name at index 7 above to see what happens. The index must be between 0 and the length of the array - 1 or it will give an error message called ArrayIndexOutOfBoundsException.
Note also that the index can be any expression, not just a literal int. In fact, it is somewhat unusual to use a literal index. More likely we will use at least a variable or even a more complex arithmetic expression. For instance given an array like highScores, the expression highScores.length - 1 gives us the index of the last element of the array. Here are some examples, assuming i is an int variable that is a legal index into highScores:
highScores[i];                                         // Score at index i
highScores[i + 1];                                     // Next score
highScores[highScores.length - 1];                     // Last score
highScores[(int (Math.random() * highScores.length)]); // Random score

Activity 6.1.9. Random images.

This code contains an array of image filenames. Run the code and see that it displays images[0] which is β€œcow.jpg”. Can you change the index variable’s value so that it prints out the puppy image? Can you print out the reindeer? Try all of them! What indices did you need to use? Then try using a random number for the index instead. Remember that (int) (Math.random() * max) will return a number from 0 up to max. What’s the maximum number it can be for this array?

Subsection 6.1.5 Array references as arguments

In SectionΒ 3.1Β Writing methods we mentioned that Java uses call by value when it passes arguments to methods. That means that when pass arguments in a method call, the argument values are stored in the parameters defined in the method. For primitive types that means a copy of the actual value. But for reference types, like arrays, that means a copy of the referenceβ€”the number that allows access to the actual object data of the array. And through a reference it’s possible to change the actual data in the array so the change is visible after the method returns.
To see why this difference matters, consider these three listings.
Listing 6.1.4. Method that (uselessly) changes the value of its int parameter
public void changeIntParameter(int n) {
  // changes the variable n
  n = 20
}

int num = 10;
changeIntParameter(num); // pass copy of the value 10
System.out.println(num); // prints 10
In this listing the method changeIntParameter accepts an int argument which is stored in the parameter n. That parameter is a variable that only exists until changeIntParameter returns. In this method, n is assigned a new value but the code has no effect because immediately after that the method returns and the variable n doesn’t exist any more. The assignment to n has no effect on wherever its argument value came from. In this case because the argument came from the variable num some people expect the change to n to also change num. But it’s the value of num that was passed to changeIntParameter. This would perhaps be more obvious if we had instead called changeIntParameter(10). Few people would expect the value of 10 to suddenly be 20!
Now consider this listing where the code works almost exactly like the previous one:
Listing 6.1.5. Method that (uselessly) changes the value of its int[] parameter
public void changeArrayParameter(int[] ns) {
  // changes the variable ns
  ns = new int[] { 20 };
}

int[] nums = new int[] { 10 };
changeArrayParameter(nums); // pass copy of reference to nums
System.out.println(nums[0]);  // prints 10
In this code the variable nums is a reference to a newly created int[] rather than just an int. But when changeArrayParameter is called, a copy of that reference is passed as the argument and stored in the method’s parameter ns. Then, like the code in changeIntParameter, changeArrayParameter immediately assigns a completely new value to its parameter, clobbering the one that was there just like changeIntParameter clobbered the value 10 with the new value 20. Then the method returns and the change to ns no longer matters because ns no longer exists.
Now consider this final listing which works quite differently than the first two:
Listing 6.1.6. Method that changes the value of its an array element via argument reference
public void changeArrayElement(int[] ns) {
  // changes the referenced array
  ns[0] += 10;
}

int[] nums = new int[] { 10 };
changeArrayElement(nums); // pass copy of reference to nums
System.out.println(nums[0]);  // prints 20
As in the previous listing the variable nums is a reference to a newly created array and a copy of that reference is passed to changeArrayElement where it is stored in the parameter ns. But changeArrayElement doesn’t assign a new value to ns. Instead it uses an array access expression to assign a new value to the zeroth element of the referenced array. Since nums and ns are both references to the same underlying object data, this assignment actually changes the array so the change is visible after changeArrayElement returns.

Activity 6.1.10.

The following method has the correct code to subtract amt from all the values in the array values, but the code is mixed up. Drag the blocks from the left into the correct order on the right. You will be told if any of the blocks are in the wrong order.

Subsection 6.1.6 Coding Challenge: Countries Array

In this challenge, you will create a guide to different countries using arrays.
  1. Use the Active Code window below to create four parallel arrays and initialize them using initialization lists that represent the data below. Remember that the order of these arrays has to match so that you can use the same index and get corresponding values out.
    • Countries: China, Egypt, France, Germany, India, Japan, Kenya, Mexico, United Kingdom, United States
    • Capitals: Beijing, Cairo, Paris, Berlin, New Delhi, Tokyo, Nairobi, Mexico City, London, Washington D.C.
    • Languages: Chinese, Arabic, French, German, Hindi, Japanese, Swahili, Spanish, English, English
    • Filenames for map images: China.jpg, Egypt.jpg, France.jpg, Germany.jpg, India.jpg, Japan.jpg, Kenya.jpg, Mexico.jpg, UK.jpg, US.jpg
  2. You are encouraged to add additional country, capital, and language names that match in position in the parallel arrays to represent your family origins or places you would like to visit. Although we do not have image files for each country in the CSAwesome map images, we do have regional map images called south-america.png, central-america.png, north-america.png, asia-pacific.png, europe.png, africa.png, and middle-east.png which you can use. Note that these are png files and not jpg. If you create more maps for your project, you can have your teacher share it in the teaching-csawesome google group to contribute to this map image collection.
  3. Choose a random number using Math.random() and the length of one of the arrays and save it in a variable called index.
  4. Print out the country name, its capital, and its language, and the map image for that country using the random index to access the corresponding item in each parallel array. For the images, the printHtmlImage method has been given to get the image URL online and print it out as an HTML image.

Project 6.1.11.

Create four parallel arrays to keep information about countries. Randomly pick an index to show the information about the countries.

Subsection 6.1.7 Summary

  • (AP 4.3.A.1) An array stores multiple values of the same type. The values can be either primitive values or object references.
  • (AP 4.3.A.2) The length (size) of an array is established at the time of creation and cannot be changed. The length of an array can be accessed through the length attribute.
  • (AP 4.3.A.3) When an array is created using the keyword new, all of its elements are initialized to the default values for the element data type. The default value for int `` is ``0, for double is 0.0, for boolean is false, and for a reference type (like String or a class you have created) is null.
  • (AP 4.3.A.4) Initializer lists can be used to create and initialize arrays.
  • (AP 4.3.A.5) Square brackets [] are used to access and modify an element in a 1D (one dimensional) array using an index.
  • (AP 4.3.A.6) The valid index values for an array are 0 through one less than the length of the array, inclusive. Using an index value outside of this range will result in an ArrayIndexOutOfBoundsException.

Subsection 6.1.8 AP practice

We will see in the next lesson that the index of an array is often a variable named i that is used in loops to traverse an array. In challenging AP problems, you will see mathematical expressions inside the square brackets ([]). For example, array[i-1] refers to the previous element right before the ith element in array, and array[i+1] refers to the next element after the ith element. In the problems below, note that arrays can be passed in as arguments to methods and returned as values, just like any variable.

Activity 6.1.12.

Consider the following method. Given an array initialized to {4, 10, 15}, which of the following represents the contents of the array after a call to mystery(array, 2)?
public void mystery(int[] a, int i)
{
   a[i] = a[i-1] * 2;
}
  • [8, 20, 30]
  • This would only be true if all elements were doubled by the method.
  • [4, 8, 15]
  • This would only be true if the call was ``mystery(array, 1)``. Remember that array indexing starts at 0.
  • [8, 10, 15]
  • This would only be true if the method body had ``a[i-1] = a[i-1] * 2;``
  • [4, 10, 20]
  • Correct. array[2] = array[1] * 2 = 10 * 2 = 20.
  • [4, 8, 30]
  • Note that only 1 array element is changed.

Activity 6.1.13.

Consider the following method. Which of the following code segments, appearing in the same class as the mystery method, will result in array2 having the contents {5, 10, 20}?
public int[] mystery(int[] a, int i, int value)
{
   a[i + 1] = a[i] + value;
   return a;
}
  • int[] array1 = {5, 10, 15};
    int[] array2 = mystery(array1, 0, 10);
    
  • This would result in {5, 15, 15}.
  • int[] array1 = {5, 15, 20};
    int[] array2 = mystery(array1, 0, 0);
    
  • This would result in {5, 5, 20}.
  • int[] array1 = {5, 10, 15};
    int[] array2 = mystery(array1, 1, 10);
    
  • Correct! a[i+1] = a[2] = a[i] + value = a[1] + 10 = 10 + 10 = 20.
  • int[] array1 = {5, 15, 20};
    int[] array2 = mystery(array1, 2, 0);
    
  • This would result in an ArrayIndexOutOfBoundsException.
  • int[] array1 = {5, 10, 15};
    int[] array2 = mystery(array1, 1, 20);
    
  • This would result in {5, 10, 30}.
You have attempted of activities on this page.