Skip to content

VOL 01 / CH 06 / LESSON 02

6.2 Array Indexing and Traversal ​

Prerequisites: Array declaration, index boundaries, and loops

Estimated time: 20 minutes

You are ready to continue when: You can choose a loop for indices, element updates, or reverse access

scores contains five marks: 85, 92, 78, 95, and 88. Five handwritten print statements might be manageable, but a longer array needs a loop to handle its indices.

1. Index Loop Provides Position and Value ​

java
int[] scores = {85, 92, 78, 95, 88};

for (int index = 0; index < scores.length; index++) {
    System.out.println("Student " + (index + 1)
            + ": " + scores[index]);
}

Output:

text
Student 1: 85
Student 2: 92
Student 3: 78
Student 4: 95
Student 5: 88

The loop condition uses index < scores.length. When the index equals the length, the loop ends, and no out-of-bounds access occurs. The length of an empty array is 0, so the condition fails on the first check, resulting in the loop body executing 0 times.

When modifying components in place, use the index:

java
for (int index = 0; index < scores.length; index++) {
    scores[index] = Math.min(100, scores[index] + 5);
}

This assumes the input scores have already been checked to lie in 0–100, then caps the adjusted result at 100. If the business allows values exceeding 100, this rule should be removed; the code should not secretly decide boundaries on behalf of the business.

2. Enhanced for When Only Values Matter ​

java
for (int score : scores) {
    System.out.println("Score: " + score);
}

The enhanced for sequentially retrieves the value of each component and assigns it to the loop variable score. It does not directly expose the index, making it suitable for reading, counting, and calling methods that only require the element value.

Reassigning the loop variable does not replace the array components:

java
int[] values = {1, 2, 3};
for (int value : values) {
    value = 0;
}
System.out.println(java.util.Arrays.toString(values));
// [1, 2, 3]

When referring to the loop variable as a copy, be mindful of the component type:

  • For int[], a copy of the integer value is made.
  • For arrays of reference types such as String[] and Person[], a copy of the reference value is made. Reassigning the loop variable does not replace the array components, but modifying the mutable object through the reference will still be observable in the array's references.

Java's parameter passing follows the same pattern: always pass by value. When an array is passed to a method, a copy of the array reference value is made. The method can modify the components through the copied reference, but it cannot replace the caller's variable simply by reassigning the parameter.

java
static void changeFirst(int[] values) {
    values[0] = 99;
}

static void replaceLocally(int[] values) {
    values = new int[]{7, 8, 9}; // Only modify the parameter variable
}

Calling changeFirst(original) will modify original[0]; calling replaceLocally(original) will not make original point to a new array.

3. Reverse and Adjacent Access Require Prior Derivation of Boundaries ​

Reverse Output:

java
for (int index = scores.length - 1; index >= 0; index--) {
    System.out.println(scores[index]);
}

When the array is empty, the initial value is -1, and the condition fails immediately. The index here is int; if the language used were an unsigned index type, the reverse approach might require adjustment.

When comparing adjacent elements, the loop only needs to run up to the second-to-last position:

java
for (int index = 0; index + 1 < scores.length; index++) {
    long difference = (long) scores[index + 1] - scores[index];
    System.out.println(difference);
}

Do not memorize the loop template first. First, write down which indices the loop will access, and then work backward to derive the conditions that ensure all accesses are valid.

4. Define Empty-Input Behavior for Statistics ​

Summing over an empty array can naturally return 0:

java
static long sum(int[] values) {
    long total = 0L;
    for (int value : values) {
        total = Math.addExact(total, value);
    }
    return total;
}

Calculating an average, however, requires deciding the meaning of an empty array:

java
static double average(int[] values) {
    if (values.length == 0) {
        throw new IllegalArgumentException("empty values");
    }
    return (double) sum(values) / values.length;
}

If values is allowed to be null, the contract should specify whether it should be rejected, treated as an empty array, or have some other meaning. The above implementation causes null to produce NullPointerException, which suits an internal API that treats a null argument as a caller error. Public APIs often use Objects.requireNonNull(values, "values") to provide more explicit messages.

5. Choosing a Traversal Method ​

RequirementRecommended ApproachReason
Read each value individuallyEnhanced forAvoid exposing unnecessary indices
Modify an array componentIndex forWritable values[index]
Need position or adjacent valuesIndex forPosition participates in calculation
Reverse accessIndex forClearly control start and direction
Process multiple arrays at corresponding positionsIndex forFirst validate length relationships

A stream API can also handle arrays, but before mastering loops, boundaries, and side effects, it's not advisable to wrap simple traversal in more complex expressions that are harder to debug.

Language Difference Window ​

Python's enumerate simultaneously provides both index and value:

python
scores = [85, 92, 78, 95, 88]
for index, score in enumerate(scores):
    print(f"Student {index + 1}: {score}")

C++17's range-based for can bind by value or by reference. for (int value : values) modifies local values, while for (int& value : values) can modify the original component. This differs from Java's enhanced for reference model, which cannot be simply analogized by appearance.

Common Issues ​

PhenomenonFirst Check
Out-of-bounds in the last iterationIs it written as index <= values.length
Enhanced for loop modification is ineffectiveIs the loop variable only being reassigned
Attempting to calculate average of empty array results in exception or NaNIs an empty input strategy defined
Method modifies original arrayIs a component written through a copied reference
Out-of-bounds access while traversing two arrays togetherIs the length validated first or handled by the shorter length

Before Moving On ​

Walk through the forward, reverse, and adjacent element loops with empty arrays, single-element arrays, and three-element arrays. When modifying components, indicate the position where the index is written back. When using the enhanced for, explain whether the loop variable copies a primitive value or a reference value. Calculating the average also requires deciding the agreement for empty input and null.

→ Next: Array Operations and Tools

Built with VitePress | Software Systems Atlas