Skip to main content

Section 7.2 Iterating Over Array Elements

Because arrays use integer indexes within square brackets to access elements, we can access these elements sequentially using iteration and a counter variable, similar to the way we accessed elements in ArrayLists. Like an ArrayList, we can ask an array for its length. Unlike an ArrayList, the length of an array is determined using the .length property instead of the size() method which is used for an ArrayList. Recall that when iterating over the elements of an ArrayList, our loop counter had to stop at a value of 1 less than the size of the ArrayList. If the first index is 0, the last index is size()-1. The same argument applies to arrays. The first index is 0, so the last index is .length - 1. The test for continuation when iterating over the elements of an array must check that the counter is less than the length of an array, not less-than or equal-to. Take note of the form of the continuation tests in the following for-statement examples.

Subsection 7.2.1 Arrays with For-statements

Listing 7.2.1 is an updated version of Listing 5.5.2, with a few changes. First, we use an array instead of an ArrayList to hold all Oval object references. Second, we change the while-statement to a for-statement. As you study the example, note that the number of Oval objects to create is set when declaring the array near the top of the program. For the iteration continuation test, we interrogate the array for its length instead of entering a value explicitly, and check that the loop counter is less-than the array length. It is better to interrogate the array instead of entering the value into the for-statement because it is less error-prone if later we decide to modify the number of Oval objects. Only one change is made instead of searching the program for all instances of 20.
// RandomOvals2.java
import java.util.Random;                      // Import classes
import doodlepad.*;                           // Import DoodlePad classes

public class RandomOvals2 {                   // public class
  public static Oval[] ovals = new Oval[20];  // Array of 20 Ovals

  public static void main(String[] args) {    // Start of execution

    // Fill array with randomly placed Oval objects
    // Use a for-statement to iterate the size of the array
    for (int i=0; i<ovals.length; i++) {      // For-statement
      ovals[i] = new Oval();                  // Create an Oval object
      ovals[i].setMousePressedHandler(RandomOvals2::recolor);
    }
  }

  // Event handler method that executes when an Oval is clicked
  public static void recolor(Shape shp, double x, double y, int button) {
    int r, g, b;                              // Helper variables
    Random rnd = new Random();                // Declare Random object

    // Loop over all Oval objects and reset to a random fill color
    for (int i=0; i<ovals.length; i++) {      // For-statement
      r = rnd.nextInt(256);                   // Random color components
      g = rnd.nextInt(256);
      b = rnd.nextInt(256);
      ovals[i].setFillColor(r, g, b);         // Change fill color
    }
  }
}
Listing 7.2.1. RandomOvals2.java
Figure 7.2.2. RandomOvals2.java

Subsection 7.2.2 Arrays with For-each Statements

As is the case for ArrayLists and other Java Collection objects, we can use the for-each statement to iterate over the elements of an array. In this case we do not use a loop counter because the for-each statement syntax avoids the need for a counter. If the only purpose of a loop counter is to access existing array elements, the for-each statement might be a better option because fewer moving parts mean less opportunities to make a mistake. Without the loop counter we avoid the opportunity to incorrectly check the condition for continuation and to incorrectly update the loop counter. We have plenty of opportunities to make mistakes. It is best to limit these opprotunities as much as possible.
In the code snippet below we rewrote the for-statement in the recolor(โ€ฆ) method of Listing 7.2.1 as a for-each statement. No loop counter is necessary because the for-each accesses array elements in sequence and iterates the correct number of times. We cannot replace the for-statement in the main(โ€ฆ) method with a for-each. Do you see why?
// Loop over all Oval objects and reset to a random fill color
for (Oval o: ovals) {
  r = rnd.nextInt(256);                   // Random color components
  g = rnd.nextInt(256);
  b = rnd.nextInt(256);
  o.setFillColor(r, g, b);                // Change fill color
}
The for-statement in Listing 7.2.1 cannot be replaced with a for-each because the loop counter is used for more that just accessing existing objects. We use it to set references to new objects in the array as well. It is not possible to initialize array elements with a for-each statement.

Subsection 7.2.3

Letโ€™s compare two of our most important data structures.
Table 7.2.3. array vs. ArrayList
Feature ArrayList array
Creating Uses new with
the constructor
Uses new with
[] and size
Reading the
number of items
Use the .size()
method
Use the .length
property
Accessing element
value
Use the .get(index)
method
Use the [index]
notation
Updating element
value
Use .set(index, val)
or .add(val) methods
Use the [index]
notation