18. Arrays

Key concepts

  1. Arrays as basic collections; array types
  2. Creating Arrays
  3. Indexed Access
  4. Iterating over arrays

Introduction

So far we've seen two powerful collection classes in Java -- the ArrayList and HashMap. In this lesson, we'll see a more primitive mechanism for representing a collection, called an array. In many programming languages (particularly older languages, such as C), arrays are the only mechanism for representing collections of data, and programmers typically use arrays to build higher-level collection abstractions that are more convenient and flexible to use.

Creating Arrays

Arrays are a very simple kind of collection. They are fixed in size and provide indexed access. For example, let's say we want to store the rainfall data for a week's rainfall. Here's how we can create an array of seven numbers, one for each day:
double[] rainfall = new double[7];
double[] is the type of the array -- an array of doubles. rainfall is the name that we're going to use to refer to the new array object (it can be any identifier we like). 7 is the size of the array that we're going to build (it can be any expression). new double[7] creates the new array-of-doubles object, with the given length. We can draw the resulting picture as follows:

Indexed Access

Now we'd like to put the rainfall data in it. To assign to the elements of the array, we use indexing. Indexing into arrays is very similar to indexing into ArrayList objects, except that the syntax is different. Here's how we might set the rainfall data:
rainfall[0] = 0.1;  // Sunday's rainfall
rainfall[1] = 0.0;  // Monday's rainfall
rainfall[2] = 1.5;  // Tuesday's rainfall; a real gusher
rainfall[3] = 0.7;  // Wednesday's rainfall
rainfall[4] = 0.0;  // Thursday's rainfall
rainfall[5] = 0.0;  // Friday's rainfall
rainfall[6] = 0.1;  // Saturday's rainfall
The number in brackets (0 - 6) is the index. Like ArrayList objects, the first element of an array is always at index 0, and other elements follow sequentially after that. So for an array of size N, the indices of the elements are in the range 0..N-1.

We use indexing to get things back out of the array, too:

double mondaysRainfall = rainfall[1];
double weekend_rainfall = rainfall[0] + rainfall[6];
Notice that we do not need a cast operation (as we did when we accessed elements of an ArrayList), because we expressed the type of the array elements when we created the array. In general, the indices can be any expression, so we can compute which elements we want to store into or fetch from. For example:
rainfall[x + y - z] = rainfall[x - y * z] * 5;
We can make arrays of any kind of object, not just numbers. Here's an array of Rectangles:

Rectangle[] rectangles = new Rectangle[4];
rectangles[0] = new Rectangle(0, 0, 100, 200);
rectangles[1] = new Rectangle(200, 200, 10, 20);
rectangles[2] = new Rectangle(300, 300, 100, 40);
rectangles[3] = new Rectangle(100, 100, 10, 20);

Again, we use indexing to access elements of our array:

Rectangle aRectangle = rectangles[2];
In general, we use the following pattern for accessing an array:
<array-name>[<index-expression>]

Iterating Over Arrays

As with other collections, if we wish to visit every element of an array, we'll need to use iteration. For example, here's how we can compute the total rainfall for a week:
// assume we've created and filled an array of rainfall data

int totalRainfall = 0;

for (int day = 0; day < 7; day++) { 
  // day is in the range 0..6 here
  double dayRainfall = rainfall[day];
  totalRainfall = totalRainfall + dayRainfall;
}

// totalRainfall now has the right answer
In the loop body, rainfall[day] looks up the rainfall for the particular day.The loop makes this variable go through all the elements of the array. A standard pattern for looping over an array is
for (<indexName>=0; <indexName> < <array-length>; <indexName>++) {
  ... array[<indexName>] ...
}

In this example, we knew that the rainfall data was for a week, so we used the constant 7 as the upper limit of the loop. But in the future, we might change it to be for a month, or a year, or anything else. To make our code be more adaptable to future changes to the size of the rainfall array, as well as to make the code clearer to the reader ("what does 7 mean?", they might ask), we can change it to use a final Java feature of arrays: asking their length.

The expression a.length evaluates to the length of the array a. We can use this expression as the upper limit of the for-loop:

// assume we've created and filled an array of rainfall data

int totalRainfall = 0;

for (int day = 0; day < rainfall.length; day++) { 
  double dayRainfall = rainfall[day];
  totalRainfall = totalRainfall + dayRainfall;
}

// totalRainfall now has the right answer
This is a much better implementation of this loop, since it will automatically adapt to some kinds of program changes.

An even better idea is to anticipate that we might be wanting to calculate sums of arrays of numbers in other applications too, and so implement a function just for that purpose:

// in some class, e.g. ArrayFunctions
public static double sum(double[] array) {
  int total = 0;
  for (int index = 0; index < array.length; index++) {
    // index is in the range 0..(array.length-1) here
    total = total + array[index];
  }
  return total;
}
This function can then be called to compute the total rainfall data for a week:
int totalRainfall = ArrayFunctions.sum(rainfall);
We've now created a method that is readable and robust to future changes. Furthermore, it can be debugged once and then reused in lots of other contexts.


Ben Dugan & UW-CSE, Copyright (c) 2001.