Accumulator, Sentinel, and Choosing the Loop Shape
Two patterns that cover most real loops, and a decision tree for picking the shape
A loop can do more than count or print. Most of the loops you will write in this course collect something across iterations — a running sum, a running product, the largest value seen so far. The variable that holds the collected result is called an accumulator: it lives outside the loop, is initialized before the loop starts, and is updated in the body each pass.
A loop can also stop when the body tells it to — when the user types a special value, when a search finds what it was looking for, when a computation falls below a threshold. That’s the sentinel pattern. Combined with the “choose the loop shape” decision tree at the end, these two patterns cover most of what real-world Java 1 loops actually look like.
In a nutshell
The accumulator pattern has three parts: an initial value (the identity for your operation), an update inside the loop body, and a read after the loop ends. The initial value matters — 0 for sums, 1 for products, the first input for max/min.
The sentinel pattern has three parts: a priming read before the loop, a condition that checks whether the read was the sentinel, and a re-read at the end of the body so the loop always checks fresh input. The sentinel value itself is never processed — the loop exits before touching it.
The flag pattern uses a boolean to signal “stop.” When the stop condition is computed from state rather than matched against a single input value, declare a boolean done = false; outside the loop, loop while (!done), and let the body set done = true; once its work is finished. Reach for it when “we’re done” is too complex to fit cleanly in the loop header.
Choose the loop shape by asking three questions, in order: (1) must the body run at least once? → do-while. (2) Is the iteration count known up front? → for. (3) Does the body determine when to stop? → while (with a sentinel, a flag, or any computed condition). All three shapes can express any loop; you choose for readability.
Quick reference
Accumulator initial values (the identity rule)
| Operation | Initial value | Reason |
|---|---|---|
| sum | 0 |
0 + x = x |
| product | 1 |
1 * x = x |
| max | first input | nothing is “less than” the first value |
| min | first input | nothing is “greater than” the first value |
| count | 0 |
start with nothing counted |
Sentinel pattern skeleton
int x = in.nextInt(); // priming read BEFORE the loop
while (x != SENTINEL) {
// process x here
x = in.nextInt(); // re-read at the END of the body
}
Flag pattern skeleton
boolean done = false;
while (!done) {
// do the work for one pass
if (/* whatever "we're done" means */) {
done = true;
}
}
The three-question decision tree
Does the body run at least once?
|
YES +-------+------- NO
| |
do-while Is exact count known up front?
YES | NO
| |
for Does the body determine termination?
YES | NO
| |
while (re-read the problem)
Deep dive
1. The accumulator pattern: running sum
Plan. Sum N integers read from Scanner.
- Declare
int sum = 0;— the identity for addition. - Read
N. - Loop
Ntimes. Body: read the next integer, add it tosum. - After the loop: print
sum.
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int sum = 0; // accumulator; identity for addition
for (int i = 0; i < n; i++) {
int x = in.nextInt();
sum += x; // update the accumulator every pass
}
System.out.println("sum = " + sum);
Sample run (N = 4, then 10 20 30 40):
sum = 100
Invariant. At the top of iteration i, sum equals the total of all values read so far. That sentence is worth writing as a comment above the loop — it forces you to say exactly what the loop is doing.
2. Running product — same skeleton, different identity
Plan. Compute the product of N integers. Identity for multiplication is 1.
int product = 1; // identity for multiplication
for (int i = 0; i < n; i++) {
int x = in.nextInt();
product *= x;
}
If you initialize product = 0, every multiplication gives zero and you end up with 0 regardless of input. The identity rule is not a suggestion — it is the reason the accumulator works.
3. Running max — why the initial value matters
Finding the maximum uses the same shape: an accumulator, updated in the body. The update rule changes: compare, and keep the larger value.
Plan. Find the max of K inputs. Initialize max to the first input, then loop over the remaining K − 1.
Scanner in = new Scanner(System.in);
int k = in.nextInt();
int max = in.nextInt(); // prime: first input is the initial max
for (int i = 1; i < k; i++) { // already read one; loop k-1 more
int x = in.nextInt();
if (x > max) {
max = x;
}
}
System.out.println("max = " + max);
Sample run (k = 3, then -5 -2 -9): max = -2.
Pitfall — initializing
maxto 0 when inputs can be negative. If you writeint max = 0;and every input is negative, the body never updatesmax— every input is less than 0, sox > maxis always false. The program printsmax = 0, which is wrong. Failure signature: running max returns 0 when all inputs are negative. If you see that, check your initialization.The fix is the first-input rule: initialize
maxto a real input value. No subsequent value can be “smaller than anything real,” because there is no “smaller than anything.”
4. Running min — the mirror
Replace > with <. Initialize min to the first input by the same rule.
int min = in.nextInt();
for (int i = 1; i < k; i++) {
int x = in.nextInt();
if (x < min) {
min = x;
}
}
5. The sentinel pattern
Sometimes you do not know how many values you will read. The user has a list, but they did not tell you in advance how long it is. You need a way for them to say “I’m done.” That signal is a sentinel — a value outside the valid input range that acts as a stop cue.
Pick a sentinel the problem guarantees will not appear as real data. For a list of positive integers, -1 works. For a list that could include -1, use -999 or whatever the spec reserves.
The priming-read idiom. Read one value before the loop. The loop condition tests whether that value is the sentinel. If it is not, process it — then read the next one at the end of the body. On the next condition check, the new value is tested.
Plan. Read integers, sentinel -1, compute the sum.
Scanner in = new Scanner(System.in);
int sum = 0;
System.out.print("enter a number (-1 to stop): ");
int x = in.nextInt(); // priming read
while (x != -1) {
sum += x; // process the real value
System.out.print("enter a number (-1 to stop): ");
x = in.nextInt(); // re-read at end of body
}
System.out.println("sum = " + sum);
Sample run:
enter a number (-1 to stop): 10
enter a number (-1 to stop): 20
enter a number (-1 to stop): 5
enter a number (-1 to stop): -1
sum = 35
Key insight — the sentinel is never processed. When the user types
-1, the conditionx != -1is false and the loop exits before the body runs. If you accidentally add the sentinel to the sum, it is because you placed the re-read at the top of the body rather than the bottom. Structure: read, check, process, re-read, check again.
What if the sentinel is typed first? The priming read sets x = -1. The condition -1 != -1 is false. The body never runs. sum stays 0 and the program prints sum = 0. That is correct — zero real values were entered. This is why the priming read sits outside the loop: the condition needs something to test on the first check.
0, but it always returns a sum that is off by the first value entered. What is the bug?
int sum = 0;
int x;
while ((x = in.nextInt()) != 0) {
x = in.nextInt(); // read next value
sum += x;
}in.nextInt() in the condition consumes a value that gets tested but then immediately overwritten by the second in.nextInt() in the body. Use the standard structure: one priming read before the loop, one re-read at the end of the body. Never read twice per pass.
6. The flag pattern — when the stop signal is computed, not read
The sentinel pattern works when one specific input value cleanly means “stop.” Sometimes the stop condition is more complex — a running total crosses a threshold, a search finds its target, two consecutive inputs are equal. The flag pattern uses a boolean variable as a switch: the body sets it to true when the work is finished, and the loop condition tests the flag.
Plan. Read integers and add them to a running sum. Stop as soon as the sum exceeds 100. Print how many integers it took.
Scanner in = new Scanner(System.in);
int sum = 0;
int count = 0;
boolean done = false;
while (!done) {
sum += in.nextInt();
count++;
if (sum > 100) {
done = true;
}
}
System.out.println("Took " + count + " integers; sum = " + sum);
The condition !done reads as “while we are not done.” The body owns the decision to flip the flag. Once it does, the next condition check exits the loop.
Pitfall — flag set, but body keeps going. Setting
done = truedoes not exit the loop on the spot. The flag only takes effect on the next condition check, so any code after the flag-set still runs in the current iteration. If you need to stop work mid-body, restructure the body so nothing follows the flag-set, or usebreak(lesson 4-e).
Sentinel vs. flag — how to choose. A sentinel works when one input value reliably means “stop” (
-1in a list of positive integers). A flag works when the stop condition is computed from accumulated state. Both producewhileloops; the flag just makes a complex termination condition readable as English.
7. Choosing the loop shape
All three loop shapes can express any loop. You choose between them for readability. Here’s the decision tree applied to five English problem statements.
(1) “Print the integers from 1 to 100.”
Body at least once? Not required. Count known up front? Yes, 100 iterations. → for.
(2) “Read numbers until the user types -1; print the average.”
Body at least once? No (user might type -1 immediately). Count known? No. Body determines termination? Yes. → while (sentinel).
(3) “Keep doubling a number until it exceeds one million.”
At least once? Possibly not (if the number already exceeds a million, zero iterations is correct). Count known? No. Body determines termination? Yes. → while.
(4) “Read N temperatures from Scanner and find the maximum.”
At least once? Not required. Count known? Yes, N. → for (with first-input initialization for max).
(5) “Prompt for a positive integer; re-prompt until they give one.”
At least once? Yes — you cannot validate what you have not read. → do-while (lesson 4-e).
The
do-whilecase usually sounds like “prompt until valid” or “retry until correct.” If the problem can complete in zero iterations (user was right the first time, or there is no input at all), it is notdo-while. The distinguishing question: is the first iteration unconditional?
8. The five-step English-to-Java plan
Knowing the shape is half the job. Writing code from an English description is the other half. Use five steps, in order, every time.
- What varies each iteration? Name the loop variable.
- When do we stop? Write the continue condition as a boolean expression.
- What happens each time? Describe the body in one sentence.
- What gets tracked across iterations? List every variable that persists outside the loop (counters, accumulators, the priming-read variable).
- Which loop shape? Apply the decision tree.
Worked translation. “Read integers (sentinel -1), count how many are positive.”
// Step 1: What varies? x, each integer read from Scanner
// Step 2: When stop? x == -1; continue while x != -1
// Step 3: What each time? if x > 0, increment count; re-read x
// Step 4: Tracked across? count (0), x (priming read before loop)
// Step 5: Shape? count unknown, body reads -> while + sentinel
Scanner in = new Scanner(System.in);
int count = 0;
int x = in.nextInt(); // priming read
while (x != -1) {
if (x > 0) {
count++;
}
x = in.nextInt(); // re-read at end of body
}
System.out.println("positive count = " + count);
Sample run (input 3 -7 5 0 -1): positive count = 2.
Before you leave
The accumulator pattern holds a running result across iterations — sum, product, max, min, count. The initial value is the identity for the operation, or the first input for max/min. The sentinel pattern reads until a stop value appears; it requires a priming read and a re-read at the end of the body, and the sentinel itself is never processed. The flag pattern is the sentinel’s cousin for cases where “we’re done” is computed from state rather than read from input. Choose the loop shape with the three-question decision tree: do-while for “at least once,” for for known counts, while when the body decides (sentinel, flag, or any computed termination).
Tomorrow: loops inside loops. The inner loop restarts from its own init every time the outer loop advances — that multiplication is what lets a few lines of nested for print a full grid.
Want to practice? The Week 4 quiz-prep set on the practice platform has accumulator and sentinel problems mapped to this lesson.