Learn Java

Lesson 5Phase 1: First steps

Loops: for, while, do-while

Repeating work, the anatomy of a for loop, and how to choose between the three forms.

By Updated 55 min

  • for
  • while
  • do-while
  • loop counter
  • break
  • continue

So far, every line in your program runs once, top to bottom. But real programs are full of work that needs doing again and again: print ten lines, add up a hundred numbers, keep asking until the answer is right. This lesson is about telling the computer to repeat itself, without you having to repeat yourself.

By the end of this lesson
  • Explain why repeating work by copy-paste falls apart, and what a loop fixes.
  • Name the four parts of a for loop and say the exact order they run in.
  • Choose between for, while, and do-while for a given problem.
  • Use a do-while loop to keep asking for input until the answer is valid.
  • Use break and continue, including a labeled break that leaves two loops at once.
  • Spot the two classic loop bugs: off-by-one and the infinite loop.
From before
You already know variables and types from variables and types, the arithmetic and comparison operators from operators and casting, and how a condition drives a choice from if-else and switch. That last lesson also gave you a three-line recipe for reading a whole number typed on the keyboard. That is everything we need. A loop is really just an if that is willing to run its body more than once.

Start with the copy-paste mess#

Suppose you want to print the numbers 1, 2, 3, 4, 5 on separate lines. With only the tools you have so far, you would write five almost-identical lines.

Count.java
1public class Main {
2 public static void main(String[] args) {
3 System.out.println(1);
4 System.out.println(2);
5 System.out.println(3);
6 System.out.println(4);
7 System.out.println(5);
8 }
9}
Prints
›1
›2
›3
›4
›5

It works, but look at how brittle it is. To print up to 100 you would write 100 lines. If you decide to print each number doubled, you have to edit every single line and hope you do not miss one. The number that changes (1, then 2, then 3) is buried inside otherwise identical code. There is no single place that says “keep going until you reach the end”.

Key idea

A loop separates the work that stays the same (print a number) from the thing that changes (which number). You write the body once, and the loop runs it as many times as you ask.

The for loop, taken apart#

The for loop is built for exactly this: when you know, or can compute, how many times to repeat. Its header has three parts separated by semicolons, and then a body in braces. Here is the same counting task as a single loop.

Count.java
1public class Main {
2 public static void main(String[] args) {
3 for (int i = 1; i <= 5; i = i + 1) {
4 System.out.println(i);
5 }
6 }
7}
Prints
›1
›2
›3
›4
›5

The three parts in the header each have a job. Read them left to right:

  • Init: int i = 1. Runs once, before anything else. It sets up a variable, the loop counter, that tracks where we are.
  • Condition: i <= 5. Checked before every round. While it is true, the loop keeps going. The moment it is false, the loop stops.
  • Update: i = i + 1. Runs after each round, to move the counter along so we eventually reach the end.

And then the body in braces is the work itself: System.out.println(i). The most important thing to get right is the order these run in. It is not top to bottom. It goes like this:

  1. 1Run init once. Now i is 1.
  2. 2Check the condition. If false, stop now. If true, carry on.
  3. 3Run the body.
  4. 4Run the update.
  5. 5Go back to step 2 and check the condition again. Repeat.

Notice that init happens exactly once, and from then on it is condition, body, update, condition, body, update, and so on, until the condition finally fails. The check always comes before the body, so if the condition is false on the very first try, the body never runs at all.

Watch it run: summing 1 to 5

Press Run on the program below and step through it. Keep your eye on i and sum. You will see i climb, the condition get rechecked each time, and sum grow.

Sum.java
1public class Main {
2 public static void main(String[] args) {
3 int sum = 0;
4
5 for (int i = 1; i <= 5; i = i + 1) {
6 sum = sum + i;
7 }
8
9 System.out.println("The sum of 1 to 5 is " + sum);
10 }
11}
Prints
›The sum of 1 to 5 is 15

Trace it by hand and confirm what the visualizer shows. The body runs five times. With i equal to 1, 2, 3, 4, then 5, the running total becomes 1, then 3, then 6, then 10, then 15. When i reaches 6 the condition i <= 5 is false, so the loop stops and we print The sum of 1 to 5 is 15.

i = i + 1 has a shorthand
You met the shorter forms in operators and casting: i += 1 adds one and stores the result back, and i++ does the same in two characters. Most Java code, including later lessons of this course, writes loop headers with i++, as in for (int i = 1; i <= 5; i++). This page spells the update out as i = i + 1 so every step stays visible. All three forms do the same thing here.
Quick check
How many times does the body of for (int i = 0; i < 10; i = i + 2) run?
One more kind of for loop
Java has a fourth loop, the for-each loop, written like for (int score : scores). It walks through every value in a collection of values without a counter. It needs arrays, so you meet it in the next lesson, one-dimensional arrays.

The while loop: repeat until something changes#

Sometimes you do not know in advance how many rounds you need. You just know the rule for stopping. Maybe you keep halving a number until it reaches 1, or keep going until a total crosses some line. For that, the while loop reads more naturally. It is the barest loop: just a condition and a body.

A whileloop says “as long as this condition is true, run the body”. There is no built-in init or update slot, so you set things up before the loop and change them inside the body yourself. Here is a countdown.

Countdown.java
1public class Main {
2 public static void main(String[] args) {
3 int n = 5;
4
5 while (n > 0) {
6 System.out.println("T minus " + n);
7 n = n - 1;
8 }
9
10 System.out.println("Liftoff");
11 }
12}
Prints
›T minus 5
›T minus 4
›T minus 3
›T minus 2
›T minus 1
›Liftoff

Step through it. We start with n at 5. Each round prints the current n and then lowers it by one. After printing for 5, 4, 3, 2, and 1, the variable n becomes 0, the condition n > 0 is now false, and the loop ends. Then Liftoff prints once. That last line is outside the loop, so it runs a single time, after the loop is done.

Something in the body must move toward the exit
Notice the line n = n - 1. Without it, n would stay at 5 forever, the condition n > 0 would stay true forever, and the loop would never stop. That is an infinite loop. Every while loop needs something inside its body that nudges the condition toward false. If you ever write a loop and it seems to hang, this is the first thing to check.
Predict the outputDoubling.java
1public class Main {
2 public static void main(String[] args) {
3 int n = 1;
4
5 while (n < 100) {
6 n = n * 2;
7 }
8
9 System.out.println(n);
10 }
11}

The loop keeps doubling n while it is below 100. What number does the program print?

It prints 128, not 64. The values go 1, 2, 4, 8, 16, 32, 64. At 64 the condition 64 < 100 is still true, so the body runs once more and makes n 128. Only then does the check fail. A while loop stops at the first value that fails the test, and that value is what is left in the variable afterwards.

The do-while loop: run the body at least once#

Both loops above check the condition before the first round, so it is possible for the body to run zero times. The do-while loop flips that order. It runs the body first, then checks the condition at the bottom. This guarantees the body runs at least once, no matter what the condition says.

The shape is do { ... } while (condition);. Note the semicolon at the very end, which the other loops do not have. Watch how the body runs even though the condition is false from the start.

AtLeastOnce.java
1public class Main {
2 public static void main(String[] args) {
3 int n = 100;
4
5 do {
6 System.out.println("The body ran with n = " + n);
7 n = n + 1;
8 } while (n < 5);
9
10 System.out.println("Done");
11 }
12}
Prints
›The body ran with n = 100
›Done

Trace it. The condition is n < 5, and n starts at 100, so the condition is false immediately. Yet the body still runs once, printing The body ran with n = 100, because do-while checks the condition only after the body. Then n becomes 101, the condition 101 < 5 is false, and the loop exits. A plain while loop with the same condition would have printed nothing at all.

Key idea

A while loop may run its body zero times. A do-while loop always runs its body at least once, because it checks the condition at the end.

Asking until the answer is valid#

The classic use for at-least-once is asking a person a question: ask, read the answer, and ask again only if the answer was no good. You always have to ask once, because there is nothing to check until something has been typed. This program wants a number from 1 to 3 and keeps asking until it gets one.

Pick.java
1import java.util.Scanner;
2
3public class Main {
4 public static void main(String[] args) {
5 Scanner in = new Scanner(System.in);
6 int choice;
7
8 do {
9 System.out.print("Pick 1, 2 or 3: ");
10 choice = in.nextInt();
11 } while (choice < 1 || choice > 3);
12
13 System.out.println("You picked " + choice);
14 }
15}
Prints
›Pick 1, 2 or 3: 5
›Pick 1, 2 or 3: 0
›Pick 1, 2 or 3: 2You picked 2

The Keyboard input box holds three answers, one per line, as if someone typed 5, pressed Enter, typed 0, pressed Enter, and typed 2. Step through it. The first round reads 5, and the condition choice < 1 || choice > 3 is true, so the loop asks again. 0 also fails. 2 passes, the condition is false, and the program prints You picked 2. Change the input to a single 3 and run it again: the body runs exactly once.

The reading is the recipe from making decisions: import java.util.Scanner; at the top, Scanner in = new Scanner(System.in); to make a scanner for the keyboard, and in.nextInt() to read each whole number. Each call reads the next number in the input. Scanner gets its full explanation in Scanner and console applications.

while
do-while
Checks the condition before the body.
Runs the body, then checks the condition.
Body can run zero times.
Body always runs at least once.
No semicolon after the closing brace.
Needs a semicolon after while (...).
Use when there may be nothing to do.
Use when there is always at least one round, like asking a question.
Quick check
Which loop fits each job best? Job one: print the numbers 1 to 100. Job two: keep reading a password until the right one is typed. Job three: keep halving a number until it drops below 1.
ExerciseGuess.java
Write a guessing game. The secret number is 7. Use a do-while loop that reads a guess with in.nextInt(), adds one to count, and prints Too low or Too high when the guess is wrong. The loop ends when the guess equals the secret, and the last line then reports the number of guesses. Each test types a different series of guesses; no prompt is needed.

break and continue: changing the flow mid-loop#

Two keywords let you steer a loop from inside its body. break leaves the loop entirely, right now, skipping everything that is left. continue skips only the rest of the current round and jumps ahead to the next one (in a for loop, it still runs the update first, then rechecks the condition).

The program below walks i from 1 toward 10. It skips even numbers with continue, and it stops completely when it reaches 7 with break. Run it and watch the flow jump.

Flow.java
1public class Main {
2 public static void main(String[] args) {
3 for (int i = 1; i <= 10; i = i + 1) {
4 if (i == 7) {
5 break;
6 }
7 if (i % 2 == 0) {
8 continue;
9 }
10 System.out.println(i);
11 }
12
13 System.out.println("Loop finished");
14 }
15}
Prints
›1
›3
›5
›Loop finished

Trace it carefully, because both keywords are in play. Recall that i % 2 is the remainder when i is divided by 2, so i % 2 == 0 is true exactly when i is even.

  • i = 1: not 7, and odd, so it prints 1.
  • i = 2: even, so continue skips the print and goes to the next round.
  • i = 3: prints 3. i = 4: skipped. i = 5: prints 5. i = 6: skipped.
  • i = 7: break fires and the loop ends at once.

So the output is 1, 3, 5, then Loop finished. The numbers 7 through 10 are never reached, because break abandoned the whole loop at once. That is the difference to remember: continue means “skip the rest of this round”, while breakmeans “I am done with this loop completely”.

Loops inside loops#

The body of a loop can contain anything, including another loop. Then the inner loop runs all the way through for every single round of the outer loop. This program prints a small times table: the outer loop picks a row, and the inner loop prints that row from left to right.

Table.java
1public class Main {
2 public static void main(String[] args) {
3 for (int row = 1; row <= 3; row = row + 1) {
4 for (int col = 1; col <= 4; col = col + 1) {
5 System.out.print(row * col + " ");
6 }
7 System.out.println();
8 }
9 }
10}
Prints
›1 2 3 4
›2 4 6 8
›3 6 9 12

Step through it and watch both counters. row starts at 1, and col runs 1, 2, 3, 4, printing 1 2 3 4 on one line. System.out.println() with nothing inside ends that line. Then row becomes 2 and colstarts again from 1. Three rows of four numbers means the inner body runs 3 × 4 = 12 times, and the output is:

  • 1 2 3 4
  • 2 4 6 8
  • 3 6 9 12

Leaving both loops: a labeled break#

A plain break leaves only the loop it sits in. Inside nested loops, that is the inner one. This program is meant to search for the first pair of numbers from 1 to 4 whose product is 6, and stop there.

Predict the outputSearch.java
1public class Main {
2 public static void main(String[] args) {
3 for (int a = 1; a <= 4; a = a + 1) {
4 for (int b = 1; b <= 4; b = b + 1) {
5 if (a * b == 6) {
6 System.out.println(a + " x " + b + " = 6");
7 break;
8 }
9 }
10 }
11 System.out.println("Done");
12 }
13}

The break runs as soon as a product of 6 turns up. What does the program print?

It prints 2 x 3 = 6, then 3 x 2 = 6, then Done. The break after 2 x 3 ends the inner loop only. The outer loop carries on with a equal to 3, the inner loop starts again, and it finds 3 x 2.

To leave the outer loop as well, give it a name. A label is a name followed by a colon, written just before a loop. break search; then means “leave the loop called search”, however deep inside it you are.

LabeledSearch.java
1public class Main {
2 public static void main(String[] args) {
3 search:
4 for (int a = 1; a <= 4; a = a + 1) {
5 for (int b = 1; b <= 4; b = b + 1) {
6 if (a * b == 6) {
7 System.out.println(a + " x " + b + " = 6");
8 break search;
9 }
10 }
11 }
12 System.out.println("Done");
13 }
14}
Prints
›2 x 3 = 6
›Done

Now the output is 2 x 3 = 6 and then Done. Both loops end at the labeled break, and the program carries on with the first line after the outer loop. continue takes a label too: continue search; would end the current round of the outer loop and start its next one, with a moved on by one.

Use labels sparingly
A labeled break is a clean way out of a nested search. If you find yourself labeling loops often, the code is usually easier to follow when the search lives in its own method that returns the moment it finds the answer. Methods come in methods: parameters and return values.

Four classic programs, built with a loop#

Almost every famous beginner program is really just a loop with a small idea inside it. Here are four you will meet again and again. Read each one, then press Run and step through to watch the value build up.

Factorial: multiply 1 through n

The factorial of 5 (written 5!) is 1 * 2 * 3 * 4 * 5. The pattern is: start a running product at 1, then loop from 1 to n multiplying it in each time.

Factorial.java
1public class Main {
2 public static void main(String[] args) {
3 int n = 5;
4 int fact = 1;
5
6 for (int i = 1; i <= n; i = i + 1) {
7 fact = fact * i;
8 }
9
10 System.out.println("Factorial: " + fact);
11 }
12}
Prints
›Factorial: 120

Watch fact climb: 1, then 2, 6, 24, and finally 120. Each pass folds one more number into the running product. That “running total” shape, a variable outside the loop that the loop keeps updating, is one you will use constantly.

Fibonacci: each term is the sum of the previous two

The Fibonacci sequence starts 0, 1 and then every term is the sum of the two before it: 0 1 1 2 3 5 8 .... We keep two variables for the last two terms and roll them forward.

Fibonacci.java
1public class Main {
2 public static void main(String[] args) {
3 int n = 10;
4 int first = 0;
5 int second = 1;
6
7 System.out.print(first + " " + second + " ");
8
9 for (int i = 3; i <= n; i = i + 1) {
10 int next = first + second;
11 System.out.print(next + " ");
12 first = second;
13 second = next;
14 }
15 }
16}
Prints
›0 1 1 2 3 5 8 13 21 34

The trick is the three lines at the end of the loop: compute the next term, then slide first and second forward so they always hold the latest two. Print the first ten terms and you get 0 1 1 2 3 5 8 13 21 34.

Reverse the digits of a number

To turn 1234 into 4321, peel off the last digit with % 10, build the reversed number, then drop that digit with / 10, and repeat until nothing is left. A while loop fits perfectly, because you do not know in advance how many digits there are.

Reverse.java
1public class Main {
2 public static void main(String[] args) {
3 int num = 1234;
4 int reversed = 0;
5
6 while (num != 0) {
7 int digit = num % 10;
8 reversed = reversed * 10 + digit;
9 num = num / 10;
10 }
11
12 System.out.println("Reversed: " + reversed);
13 }
14}
Prints
›Reversed: 4321

Each pass takes the last digit (num % 10) and pushes it onto the growing reversed by multiplying the old value by ten and adding the digit. Meanwhile num / 10 chops the digit off the original. When num reaches 0, every digit has moved across, reversed.

Put the lines in orderDigitSum.java
The same digit-peeling idea adds up the digits of a number instead. Put the lines in order so the program prints Digit sum: 19 for 4096 (4 + 0 + 9 + 6). Inside the loop, the order matters: a digit has to be read before it is chopped off.

Tap a line, then tap where it should go. Or use the arrows.

Is a number prime?

A prime number is divisible only by 1 and itself. To check, try dividing by every number from 2 up to just below the number; if any divides evenly (remainder 0), it is not prime. A boolean flag remembers the verdict.

Prime.java
1public class Main {
2 public static void main(String[] args) {
3 int number = 29;
4 boolean isPrime = true;
5
6 for (int i = 2; i < number; i = i + 1) {
7 if (number % i == 0) {
8 isPrime = false;
9 break;
10 }
11 }
12
13 if (isPrime && number > 1) {
14 System.out.println(number + " is prime");
15 } else {
16 System.out.println(number + " is not prime");
17 }
18 }
19}
Prints
›29 is prime

Notice the break: the moment we find one divisor, we know the answer is “not prime”, so there is no point checking further. We flip the flag to false and leave the loop immediately. For 29, nothing divides it, the flag stays true, and we print that it is prime.

ExerciseFizzBuzz.java
A famous warm-up. Print the numbers from 1 to 15, one per line, but print Fizz instead of a number that divides evenly by 3, Buzz instead of one that divides evenly by 5, and FizzBuzz instead of one that divides evenly by both. The loop is already there; put an if / else if chain inside it.

The two classic bugs#

Loops introduce two mistakes that catch almost everyone at first. Knowing their names makes them easy to spot.

Off-by-one

This is running one time too many or one time too few, almost always because of a wrong boundary: < where you meant <=, or starting at 1 when you meant 0. Suppose you want to print 1 through 5. The loop for (int i = 1; i < 5; i = i + 1) stops at 4, because i < 5 is false when i is 5. You wanted i <= 5. The fix is always to ask: on the last value I care about, is the condition still true?

OffByOne.java
1public class Main {
2 public static void main(String[] args) {
3 System.out.println("Wrong (i < 5):");
4 for (int i = 1; i < 5; i = i + 1) {
5 System.out.println(i);
6 }
7
8 System.out.println("Right (i <= 5):");
9 for (int i = 1; i <= 5; i = i + 1) {
10 System.out.println(i);
11 }
12 }
13}
Prints
›Wrong (i < 5):
›1
›2
›3
›4
›Right (i <= 5):
›1
›2
›3
›4
›5
Infinite loops
The second bug is the infinite loop: a loop whose condition never becomes false. The usual causes are forgetting to update the counter, updating it the wrong way (counting up when the condition needs it to go down), or a condition that can never be reached. In the visualizer a runaway loop is stopped for you, but a real program would simply hang. Before you run any loop, check that something inside it truly pushes the condition toward false.

Try it

Answer each one in your head or on paper first, then open the answer.

1
Name the four parts of a for loop and say which one runs only once.
2
What does this loop print? for (int i = 0; i < 3; i = i + 1) { System.out.println(i); }
3
A while loop has the condition x < 10, and x starts at 50. How many times does the body run? Now answer the same question for a do-while loop with the same condition and start.
4
In one sentence each, say what break does and what continue does.
5
This loop is meant to print 1 through 10 but it never stops. Find the bug: int i = 1; while (i <= 10) { System.out.println(i); }
6
Rewrite the countdown from the while section as a for loop. Which line of the while version becomes the init, which the condition, and which the update?

Practice

Work through these on your own. Each one builds on this page.

1
Write a for loop that prints only the even numbers from 2 to 20, inclusive. Do it two ways: once by stepping the counter up by 2 each round, and once by stepping up by 1 and using continue to skip the odd numbers. Confirm both print the same lines.
2
Using a while loop, compute and print the factorial of 5, that is 5 * 4 * 3 * 2 * 1. Start a result variable at 1 and a counter at 5, multiply the result by the counter each round, and count down until the counter reaches 1. The answer should be 120.
3
Write a loop that prints the numbers 1 through 30, but stops the moment it reaches a number that is divisible by both 3 and 5. Use break. Which number does it stop at, and what is the last number it prints before stopping?
4
Write a program that reads whole numbers from the keyboard until it reads a 0, then prints how many numbers came before the 0 and their sum. Give it the input 4, 10, -3, 0 (one per line) and check that it reports 3 numbers with a sum of 11. A value like this 0, which means “stop” rather than being data, is called a sentinel.
5
Take the off-by-one example from this lesson. Without running it, rewrite the “wrong” loop so it correctly prints 1 through 5 by changing only the condition. Then write one sentence explaining how you decided whether to use < or <=.

Further reading#

Short guides on this topic

Quick answers to what people search for about it, with code to run.

Spotted a mistake, or a part that did not make sense? Report it by email