Processing Arrays with for Loops
A 2D array is declared with two pairs of brackets, as in int[][] A, and created with new, as in A = new int[5][7], which makes 5 rows and 7 columns.
Predicting the Output of a Grid Program
Before any rules are introduced, read the program below and decide what you expect it to print. It creates a table with two rows and three columns, fills every cell with a value, and then prints the table. Pay attention to the two loop variables and to which one changes faster. Your job at this point is only to read the code and form a prediction.
0 1 2
10 11 12- The first pair of loops fills every cell with row * 10 + col.
- The second pair of loops prints the table, with each number taking four character spaces.
- println runs after the inner loop finishes, so each row ends on its own line.
What do you think happens?
Given the nested loops above, what pair of (row, column) positions does the program visit immediately after finishing (0, 2)?
Reveal answer
(1, 0)
The inner loop stops once the column index reaches 3, so it ends after column 2 of row 0. The outer loop then moves to row 1, and the inner loop restarts at column 0.
Picking Out One Element with Two Indices
A two-dimensional array is written almost exactly like a one-dimensional array, with one difference: each element is picked out by two numbers instead of one. The first number is the row and the second is the column. If A is a 2D array of int, then A[3][2] names the element in row 3, column 2 of that array.
The row index always comes first because the array is organized as rows, and each row holds its columns. A[2][4] therefore means: go to row 2, then go to column 4 within that row. Reversing the two numbers would select a different element, or fail if the number is outside the array's bounds.
Declaring and Creating a Grid
The type of the variable carries the extra dimension. Instead of one pair of brackets, a 2D array type has two pairs of empty brackets, so an array of int is declared with int[][]. The declaration and creation can be written as two separate statements: the first names the variable and its type, and the second uses new to build the array with a stated number of rows and columns.
- int[][] A declares a variable whose type has two dimensions.
- new int[5][7] creates the array; the first number is the count of rows and the second is the count of columns.
- This array has 5 rows and 7 columns, so valid row indices run from 0 to 4 and valid column indices run from 0 to 6.
Nested Loops Visit Every Cell
Two-dimensional arrays are usually processed with nested for loops. The outer loop controls the row, and the inner loop controls the column. For each value of the row, the inner loop walks across every column in that row before the outer loop moves to the next row. This ordering is what makes the output appear in neat columns.
The diagram shows the order of visits. The column index changes fastest: it goes through every column before the row index changes. When the inner loop finishes row 0, its counter is reset, and it starts again at column 0 for row 1. The row index is the slow variable and the column index is the fast one.
Processing a Single Row or Column
Consider a company that owns 25 stores and records profit for each of 12 months in 2022. Store numbers run from 0 to 24 and month numbers from 0 to 11, so the array is declared as double[][] profit with new double[25][12]. The expression profit[3][2] gives the profit earned at store 3 in March, and profit[storeNum][monthNum] gives the profit for any store and month.
Sometimes only one row or one column is needed. To find the profit for December, which is month number 11, fix the column index at 11 and let the store index vary from 0 to 24. The loop processes one column of the table rather than the whole table.
- The column index is fixed at 11, the December position.
- Only the store index changes on each pass.
- The running total starts at zero before the loop begins.
Adding every profit entry for the year
Find the company's total profit for all of 2022, adding every entry exactly once.
- 1Initialize the total
Set
totalProfitto zero before any loop begins. Skipping this step would start the sum from whatever value the variable held before. - 2Outer loop over stores
The outer loop passes through store values 0 to 24, one store at a time.
- 3Inner loop over months
For each store, the inner loop passes through month values 0 to 11, and each entry is added to
totalProfitas it is visited. - 4Check the first two stores
Trace store 0 across months 0 to 11, then store 1 across months 0 to 11. The store index changes only after the inner loop finishes.
Every one of the 25 times 12 entries is added exactly once, so totalProfit holds the full 2022 total.
- The outer loop covers the 25 stores.
- The inner loop covers the 12 months within each store.
totalProfitis initialized to zero before the loops.
Counting Index Walks Through an Array
The index of an array element does not have to be a fixed number. It can be held in an integer variable, and the variable can be used inside the square brackets to pick out a position. The index can also be any expression whose value is an integer. This is one reason arrays are powerful: the same written code reaches different elements at different moments, depending on what the variable holds.
Think of the variable as a pointer that moves through the positions of the array. If i holds zero, list[i] names the first position. If i then holds one, the same text names the second position. Nothing about the text list[i] changes; only the value of i changes, and that changed value redirects the access.
- i starts at zero and is the array index itself.
- The condition i <
list.lengthkeeps i from reaching a position beyond the array. - i increases after each pass, so the body runs once for every valid position in order.
On the first pass the counter holds zero, so the body reads the value at position zero. On the second pass the counter holds one, and so on. When the array has five items the counter eventually equals five, the continuation condition is false, and the loop stops. The body never runs with the counter at five, so the last element printed is the one at position four.
Summing and Averaging with an Accumulator
Processing an array often means combining its elements rather than printing them. Suppose values is an array of double and you want its average. The plan has two stages. First, a loop adds every element into a running total that starts at zero. Second, the total is divided by the number of items in the array, once, after the loop has finished.
Average: 6.0- total starts at 0 and accumulates each element.
- After the loop, total is 18.0.
- The division by
values.lengthhappens once, after the loop.
The loop is the same counting pattern used for printing. Only the body has changed. Where the earlier program displayed each value, this one folds each value into an accumulator, a variable set to a starting value and updated on every pass. The accumulator pattern appears whenever a loop must gather information across all the elements.
Mistakes Beginners Make with Nested Loops
Common mistake Putting println inside the inner loop
What it looks likeEach number appears on its own line instead of forming a row.
Why it failsprintln runs on every pass of the inner loop, so it ends the line after every cell.
Do this insteadPlace println in the outer loop, after the inner loop finishes.
Common mistake Swapping the row and column indices
What it looks likeWriting grid[col][row] when the loop variable row is meant for the first index.
Why it failsThe first index always selects the row, so swapping them selects a different element or goes out of bounds.
Do this insteadWrite grid[row][col], keeping the row index first.
Common mistake Forgetting to initialize the accumulator
What it looks likeUsing totalProfit += profit[store][month] with no earlier line setting totalProfit to zero.
Why it failsThe sum starts from whatever value the variable held before, so the total is wrong even when the loops are correct.
Do this insteadSet the total to zero before the loops begin.
Common mistake Using <= instead of < with the length
What it looks likefor (int i = 0; i <= list.length; i++)Why it failsThe counter reaches length, a position beyond the array's last valid index.
Do this insteadUse i < list.length so the counter stops at length minus one.
When a 2D program prints unexpected values, trace the two loop variables separately. At each step, write down the current row, the current column, and the element the expression names, then compare that element with what you expected. Most divergences appear at one of three points: the start of a row, the end of a row, or the place where the bounds stop the loop.
Tracing a Nested Loop by Hand
Using the 2 by 3 grid from the first section, trace the second pair of loops and write down the value printed at each (row, column) position. Then check where your predicted line breaks fall and compare them with the output shown earlier. Note the first position where your reasoning differs from the printed result, if any.
Hints
- Track the row and column variables separately, one step at a time.
- Remember that the inner loop restarts at column 0 each time the outer loop advances.
- The value stored at each position is row times 10 plus column.
Key Takeaways
- A 2D array is declared with int[][] and created with new, as in new int[5][7] for 5 rows and 7 columns.
- An element is picked out by a row index followed by a column index, so A[3][2] is row 3, column 2.
- Nested for loops process a 2D array: the outer loop controls rows and the inner loop controls columns, so the column index changes fastest.
- Fixing one index and varying the other processes a single row or column, as the December profit loop does with column 11.
- A counting loop that runs while i is less than the array's length visits every element in order, and a running total gathers sums that can then be averaged.