Concepts / Looping Over Array Elements

Looping Over Array Elements

A parameter may have an array type such as int[], so one argument can deliver an entire array to a subroutine.

  • Programming

Why One Argument Can Carry a Whole Array

Suppose you want a subroutine that prints every value in an integer array in a tidy format: the values separated by commas and enclosed in square brackets. The subroutine needs to know which array to print, and in Java the way to supply that information is through a parameter. What is new here is that the type of the parameter is itself an array type, so a whole collection of values travels into the subroutine as one argument.

Before reading on, try the following situation. A caller creates an integer array holding the values 42, 17 and 256, then calls the list-printing subroutine on it. Write the exact text you expect on the screen, including where the brackets and commas fall. The rest of this article uses that prediction as a benchmark, so commit to an answer now.

Declaring an Array Parameter

A parameter's type is normally a simple type such as int, but it can also be an array type. Writing int[] as the parameter type means the subroutine accepts an integer array. The name that follows the type, here list, is the name the subroutine uses for the array inside its own body. Only the parameter name matters inside the body, so the subroutine never refers to the caller's variable name.

java
Notes on the code
  • int[] is the parameter type: an array of ints, not a single int
  • list is the name used for the array inside the body
  • list.length bounds the loop so it visits each position once
  • The brackets and commas are printed by explicit code, not by the array itself

Creating and Filling the Array First

A subroutine cannot be called with an array that does not exist yet. The array must be created and initialized first, and only then can it be passed as the argument. The source illustrates this with a short segment that declares an array variable, creates an array of three integers, fills in its elements, and then makes the call. The source calls this legal but not very realistic, since the array exists only to be handed to the subroutine. Its values, though, make a useful teaching case.

java
Notes on the code
  • numbers is declared as an array variable
  • new int[3] creates an array with room for three integers
  • The three assignments fill positions 0, 1 and 2
  • The call passes the whole array with one argument

Positions in Java arrays are numbered starting from zero. The first value sits at index 0 and the last value sits at index 2. This numbering matters again when the subroutine walks through the array.

How the Array Reaches the Subroutine

When the call printValuesInList(numbers) runs, the name numbers appears in the argument position, and the subroutine receives the array as its list parameter. The subroutine does not need to know the name numbers. It works with the array it was given through list, and every reference to list inside the body refers to that same array. The diagram shows the two names meeting at one array.

numberscaller's variableint array42, 17, 256listsubroutine parameterrefers torefers to
After the call, which names lead to the array, and does the subroutine see the caller's elements?

Because both names lead to the same array, the subroutine reads exactly the elements the caller filled in. The caller's name and the parameter name are different labels for one collection, so tracing a call means asking which array a name currently refers to, not only what the name is called.

Indexing and the length Property

Inside the subroutine, an element is reached by writing the array name followed by an index in square brackets, as in list[i]. The index says which position to read. The subroutine also needs to know how many positions exist, so it uses the length property of the array. Together these two ideas form the loop that prints the values one at a time.

list[0]42list[1]17list[2]256list.length3
Which element does each index refer to, and where does the valid range end for an array of length 3?

The valid indexes run from 0 up to length minus one. An array of length 3 has no element at index 3, even though the number 3 appears as its length. Reading past the last index is a common cause of errors in array code, so the loop bound must stop before that position.

Tracing the Loop Pass by Pass

The loop never names the values 42, 17 or 256. It reads the length and the elements from whatever array it receives, so the same subroutine works for any array of integers. The printed brackets come from the two print calls before and after the loop. The commas come from the test inside the loop, which prints a comma only when the current index is not the last one.

i = 0prints 42, then commai = 1prints 17, then commai = 2prints 256, no commai = 33 < 3 is false, stopnext passnext passnext pass
On each pass, which index is current, what is compared against length, and when does the loop stop?
Worked example

Tracing the Call with Three Values

The caller fills numbers with 42, 17 and 256 and calls printValuesInList(numbers). What exact text is printed?

  1. 1
    Before the loop

    print("[") writes an opening bracket with no newline.

  2. 2
    Pass with i = 0

    list[0] is 42, so 42 is printed. Since 0 < 2 is true, a comma and space follow.

  3. 3
    Pass with i = 1

    list[1] is 17, printed. Since 1 < 2 is true, another comma and space follow.

  4. 4
    Pass with i = 2

    list[2] is 256, printed. Since 2 < 2 is false, no comma is printed.

  5. 5
    Loop test with i = 3

    3 < 3 is false, so the loop stops without visiting index 3.

  6. 6
    After the loop

    println("]") writes the closing bracket and ends the line.

Result

[42, 17, 256]

What do you think happens?

Before reading on, what exact text does printValuesInList print when numbers holds 42, 17 and 256?

Reveal answer
Answer:

[42, 17, 256]

The opening bracket is printed before the loop. Each element is printed in turn. The comma test prints a comma after every element except the last, because only the last index equals length minus one. The closing bracket is printed after the loop ends.

Mistakes That Break Array Traces

  • Common mistake

    Passing an array before it exists or is filled

    What it looks like

    Calling printValuesInList(numbers) right after declaring int[] numbers; with no new int[3] and no assignments.

    Why it fails

    The array must be created and initialized in the calling code before it is passed as the argument.

    Do this instead

    Create the array with new, fill its positions, and only then make the call.

  • Common mistake

    Assuming the commas come from the array

    What it looks like

    Expecting the printed list to contain commas automatically because the values are stored together.

    Why it fails

    The commas and brackets are printed by explicit code in the loop and the surrounding print calls.

    Do this instead

    Trace the comma test in each pass to see when a comma is printed.

  • Common mistake

    Using length as the last valid index

    What it looks like

    Writing a loop test like i <= list.length, which would try to read list[3] for a three-element array.

    Why it fails

    Valid indexes run from 0 to length minus one, so index equal to length is out of range.

    Do this instead

    Use i < list.length as the loop test.

  • Common mistake

    Confusing the caller's variable name with the parameter name inside the subroutine

Practice: Trace a Changed Call

EASY

The caller now creates numbers holding only two values, 5 and 9, and calls the same printValuesInList subroutine. Write the exact printed text, and identify which loop pass decides that no comma follows the last value.

Hints
  • The loop bound is list.length, which is now 2.
  • Check the comma test i < list.length - 1 for i = 0 and for i = 1.
  • The brackets come from the print calls outside the loop.

Debugging an Unexpected Printout

When a subroutine that takes an array prints something unexpected, the most useful question is which step first departed from what you predicted. Check the call first: was the array created and filled before the call? Next check the parameter type. Then follow the loop one pass at a time, watching the index, the length check and the comma test. Most surprises in this subroutine come from one of these places, and tracing them in order narrows the search quickly.

Key Takeaways

  • A parameter may have an array type such as int[], so one argument can deliver an entire array to a subroutine.
  • The caller must create and initialize the array before passing it, and positions are numbered from 0 to length minus one.
  • Inside the subroutine, list[i] reads an element, and the length property bounds the loop so every position is visited once.
  • Brackets and commas in a printed list come from explicit code, so tracing each loop pass predicts the exact output.