Skip to content
Study Hall
Lesson 3 of 3Looping
Unit 4 · Lesson 3 of 3

Accumulators, Counters and Nested Loops

Building a result one pass at a time, choosing the right starting value, and putting one loop inside another to work through rows and columns.

7 min read11 practice questionsInteractiveAsk AI about this →

Key things to remember

  1. 1Declare and initialize an accumulator before the loop; change it inside. Declaring it inside resets it every pass.
  2. 2A sum starts at 0, a product starts at 1, and a counter starts at 0.
  3. 3A max or min tracker starts at the first element, and its loop then starts at index 1.
  4. 4When both bounds are fixed, total inner passes = outer passes inner passes.
  5. 5When the inner bound depends on the outer counter, add the pass counts instead of multiplying.
  6. 6break exits the loop immediately; continue skips to the next pass. Both affect only the innermost loop containing them.

A loop on its own only repeats an action. What makes loops useful is pairing them with a variable that survives from one pass to the next and gathers up the result — an accumulator. The loop supplies one value at a time; the accumulator remembers everything that has happened so far. Nearly every program that produces a total, an average, a count or a largest value is this one pattern wearing different clothes.

int[] marks = {78, 85, 92, 64};
int total = 0;                              // accumulator: declared OUTSIDE

for (int i = 0; i < marks.length; i++) {
    total = total + marks[i];               // updated INSIDE
}

double average = (double) total / marks.length;
System.out.println("Total: " + total);      // Total: 319
System.out.println("Average: " + average);  // Average: 79.75
The total climbs 78, 163, 255, 319 across the four passes. The value carried out of each pass is the value carried into the next — that carry is the whole idea.
An accumulator is one variable that keeps its value across every pass of the loop.int sum = 0; // declared OUTSIDE the loopfor (int i = 1; i <= 4; i++) { sum = sum + i; // add, then store back}ii <= 4sum beforesum = sum + isum after1true00 + 112true11 + 233true33 + 364true66 + 410i = 5 makes 5 <= 4 false, so the loop stops and sum keeps its final value of 10.Declare sum inside the loop and it is rebuilt as 0 on every pass — the running total is lost.
Fig 1One value in per pass, one running result carried forward.
Declare the accumulator outside the loop
Move int total = 0; inside the braces and two things go wrong at once. Java re-creates the variable, set back to zero, on every single pass, so the loop adds one mark to zero, throws the result away, and repeats. And because a variable declared inside a block dies at that block's closing brace, total no longer exists on the lines after the loop that read it — so this version does not even compile, and javac reports: cannot find symbol: total. The accumulator has to be declared before the loop so that it both survives every pass and is still in scope when you use the result.
PatternStart atInside the loopWhy that start
Running totalint total = 0;total += value;Adding 0 changes nothing
Running productint product = 1;product *= value;Multiplying by 1 changes nothing; 0 would trap it at 0
Counting matchesint count = 0;if (test) { count++; }You have seen nothing yet
Largest valueint max = data[0];if (data[i] > max) { max = data[i]; }The first element is the best candidate so far
Smallest valueint min = data[0];if (data[i] < min) { min = data[i]; }Same reason, opposite comparison
The right starting value is whatever leaves the answer unchanged before any data arrives.
int[] temps = {-4, -11, -7, -2, -9};    // January in Ontario, in degrees Celsius

int max = temps[0];                      // start at the FIRST element, not 0
for (int i = 1; i < temps.length; i++) { // start at 1: element 0 is already in max
    if (temps[i] > max) {
        max = temps[i];
    }
}
System.out.println("Warmest: " + max);   // Warmest: -2
Correct answer: -2. Starting max at 0 would report a warmest temperature of 0, a day that never happened.
Why a max tracker starts at the first element
Starting at 0 quietly assumes the answer is at least 0. With all-negative data no element ever beats 0, so the loop never updates and reports 0 — a value that is not even in the data. Starting at the first element makes no assumption at all: it says the best so far is the only one seen so far, which is always true. Then start the loop at index 1, because index 0 has already been counted.

Nested loops

A nested loop is simply a loop written inside the body of another loop. One rule explains all of their behaviour: the inner loop runs completely, from its first pass to its last, for every single pass of the outer loop. The outer loop advances by one, and only then does the inner loop start over from the beginning. Rows and columns are the everyday picture — the outer loop chooses the row, the inner loop walks across it.

for (int row = 1; row <= 3; row++) {
    for (int col = 1; col <= 4; col++) {
        System.out.print(row * col + " ");
    }
    System.out.println();                // end the row: OUTER loop, not inner
}

// Output:
// 1 2 3 4
// 2 4 6 8
// 3 6 9 12
Outer runs 3 times, inner runs 4 times per outer pass: 3 x 4 = 12 passes of the inner body in total.
The inner loop finishes completely for every single pass of the outer loop.for (int r = 0; r < 3; r++) { for (int c = 0; c < 4; c++) { System.out.print("*"); } System.out.println();}c=0c=1c=2c=3r=0r=1r=210,020,130,240,351,061,171,281,392,0102,1112,2122,33 outer × 4 inner = 12 runs of the bodyThe numbers show the visit order: the whole first row, then the whole second row, then the third.Total passes = outer count × inner count, so adding one row here adds four more runs, not one.
Fig 2Each cell of the grid is one pass of the inner body.
Total passes equal outer times inner — but only with a fixed inner bound
When both loops have a fixed number of passes, multiply them: an outer loop of 3 wrapped around an inner loop of 4 executes the inner body 12 times. This is also why nested loops get slow quickly — a 1000-pass loop inside another is a million passes. If the inner bound depends on the outer counter, multiplying is wrong and you must add the per-pass counts instead.
for (int row = 1; row <= 5; row++) {
    for (int star = 1; star <= row; star++) {   // inner bound depends on row
        System.out.print("*");
    }
    System.out.println();
}

// Output:
// *
// **
// ***
// ****
// *****
15 stars in total (1 + 2 + 3 + 4 + 5), not 25, because the inner loop's length grows with the outer counter.
Tracing by hand is how you find a logic error the computer will not report.total = 0i = 1while i <= 4: total = total + i i = i + 1itotalpasscondition—00—1111 ≤ 4 true2322 ≤ 4 true3633 ≤ 4 true41044 ≤ 4 true51055 ≤ 4 FALSE — exitFinal total = 10One row per pass.Write down everyvariable, every time.Forget the i = i + 1 line andthe table never ends: infinite loop.
Fig 3Write down every variable on every pass — guessing is how nested loops beat you.

Two keywords let you leave the normal loop rhythm. break abandons the loop immediately — no more passes, no update, and execution resumes at the first line after the loop. continue abandons only the current pass, jumping straight to the update and then the next condition test. In nested loops both affect only the loop they sit directly inside, so a break in the inner loop returns you to the outer loop rather than out of both. Use break to stop a search once the answer is found; if the exit rule can be written into the loop condition, write it there instead so a reader can see it.

int[] values = {4, 9, -1, 7, 12};

// continue: skip the negatives but keep going
int total = 0;
for (int i = 0; i < values.length; i++) {
    if (values[i] < 0) {
        continue;                        // skip the rest of THIS pass
    }
    total = total + values[i];
}
System.out.println(total);               // 32  (4 + 9 + 7 + 12)

// break: stop as soon as the answer is found
int firstNegative = -1;
for (int i = 0; i < values.length; i++) {
    if (values[i] < 0) {
        firstNegative = i;
        break;                           // leave the loop entirely
    }
}
System.out.println(firstNegative);       // 2
The break version stops after 3 passes instead of 5 — there is no reason to keep searching once you have found it.

Try it yourself

Loading interactive…

Worked examples

Reveal one step at a time and try to beat it to the next line.

Example 1
Trace this and give the final value of total: int[] data = {5, 3, 8, 2}; int total = 0; for (int i = 0; i < data.length; i++) { total += data[i]; }
Example 2
This finds the largest value but reports 0 for the array {-12, -3, -20, -7}. Explain and fix it: int max = 0; for (int i = 0; i < data.length; i++) { if (data[i] > max) { max = data[i]; } }
Example 3
How many times does the inner print run? for (int r = 1; r <= 4; r++) { for (int c = 1; c <= 6; c++) { System.out.print("#"); } }
Example 4
How many stars does this print? for (int row = 1; row <= 6; row++) { for (int s = 1; s <= row; s++) { System.out.print("*"); } System.out.println(); }

Where marks get lost

  • Declaring the accumulator inside the loop, so it resets every pass and the final answer is just the last value processed.
  • Starting a running product at 0 instead of 1 — zero multiplied by anything is zero, so the answer is always 0.
  • Starting a max tracker at 0 when the data can be negative, which reports a maximum that is not in the data at all.
  • Printing the total inside the loop instead of after it, which produces one line per pass instead of one final answer.
  • Putting the row-ending System.out.println(); inside the inner loop, so every single item lands on its own line.

Flashcards 10

What is an accumulator?
Where must an accumulator be declared, and why?
Starting value for a running total
Starting value for a running product
+ 6 more

Practice

1
What is the final value of total? int[] m = {78, 85, 92, 64}; int total = 0; for (int i = 0; i < m.length; i++) { total += m[i]; }
2
Moving int total = 0; inside the loop body of that program changes the answer to what?
3
What is the final value of product? int product = 1; for (int i = 1; i <= 5; i++) { product = product * i; }
4
Why should a maximum tracker start at data[0] rather than 0?
5
How many times does the inner body run? for (int r = 1; r <= 3; r++) { for (int c = 1; c <= 4; c++) { System.out.print(r * c); } }
6
How many stars in total? for (int row = 1; row <= 6; row++) { for (int s = 1; s <= row; s++) { System.out.print("*"); } System.out.println(); }
7
What is printed? int[] v = {4, 9, -1, 7, 12}; int t = 0; for (int i = 0; i < v.length; i++) { if (v[i] < 0) { continue; } t += v[i]; } System.out.println(t);
8
In one phrase, what is the difference between break and continue?
9
Order the steps of writing a loop that finds the average of an array.
  1. 1Print the average
  2. 2After the loop, cast the total to double and divide by the length
  3. 3Add the current element to the accumulator inside the body
  4. 4Declare and initialize the accumulator to 0, before the loop
  5. 5Write a for loop that visits every index from 0 to length - 1
10
Match each accumulator pattern to its correct starting value.
Running total of marks
Running product of factors
Counting how many marks pass
Tracking the largest temperature
11
A nested loop prints every item on its own line instead of in rows. What is wrong?

Spot a mistake on this page? Let us know