Overview of This Lesson

Iteration is very important in programming: a lot of programming tasks involve repetition. For example, you might want to take a list of users and send each one an email with promotions. Or you might want to have code that goes through a list of orders and sum the order totals.

Iteration is performed using loop structures. There are different kinds of these loop structures: some count from a starting value to an ending value, and some will execute indefinitely until a certain condition is met. Other loops will execute for each object or item in a list. It's not only important to learn how to write efficient loops, but also how to choose the right loop for the right job.

Pre-Requisites

Before doing this lesson, make sure you've completed all the foundational lessons and the lesson on Relational Operators and Logical Expressions.

The While Loop

There are two kinds of while loops, but this section talks about the standard While Loop, which is also referred to as the top-checking while loop or pre-test while loop. You'll understand why we use these terms in a moment.

Here is the basic syntax of a while-loop:

while (loop-continuation-condition) {
    // statement 1
    // statement 2
    // etc...
}

In a while-loop, the loop-continuation-condition is a valid relational/logical expression that evaluates to true or false. As long as this expression evaluates to true, the loop's body will execute. When the loop condition becomes false, the loop will terminate, and control will move to any statements that appear after the loop. For example, the loop below iterates 4 times and then prints "Done!":

public class BasicLoop {

    public static void main(String[] args) {

        int count = 1;
        while (count <= 4) {
            System.out.println(count + ":  Hello!");
            count++;
        }
        System.out.println(count + ":  Done!")
    }
}

The output of this loop would be:


  1: Hello!
  2: Hello!
  3: Hello!
  4: Hello!
  5: Done!

Note that the loop iterates 4 times for the values 1, 2, 3, and 4 of the count variable. Inside the last iteration, the variable gets incremented to 5. At this point, the loop condition (count <= 4) evaluates to false and the loop terminates. Then the last print statement executes; it prints the value of count followed by ": Done!".

The standard while loop is a pre-test loop, or top-checking loop. This means that the test or boolean expression that determines whether or not the loop should continue is at the top of the loop. Alternatively, the test condition can go at the bottom of the loop, as we'll see later.

Let's do another example: what do you think is the output of this loop? Try and figure it out before you run it.

public class LoopThis {

    public static void main(String[] args) {

        int number = 4
        int counter = 1;
        while (counter <= number) {
            System.out.print(counter + " ");
            counter++;
        }
        System.out.println("\nDone!");
    }
}

In this code, the program first declares number and initializes it to the value 4. Next, a counter variable is declared and initialized to 1. We need this counter to do the actual counting. We can't use the number variable, because we need that to store the value we want to count up to.

Next, the while loop condition states that the loop should continue as long as the value of the counter remains less than or equal to the value of the number variable. As long as this condition stays true, the body of the loop will execute repeatedly.

The body of the loop contains two statements - one that prints the value of the counter, and one that adds 1 to the counter. We need to increment the counter variable, otherwise the counter will always stay at its initial value and never change! This would result in an endless loop (a loop that never terminates).

For the first iteration of the loop, the counter variable has a value of 1. Then the loop condition is evaluated (is counter <= number?). Because the counter is 1 and the value of number is 4, this statement is true. The flow of execution moves inside the loop. The print() statement is executed (displaying the value of counter (1) on the screen followed by a space). Then the counter is incremented; after this statement is done, the counter has a value of 2.

Once the body of the loop is finished executing, the flow of execution goes back up to the loop condition. The condition is evaluated again: is counter <= number? This statement is true, since counter is 2 and number is 4. The body of the loop is executed again, causing the value of 2 to be printed on the screen, and the counter to be incremented to a new value of 3.

Eventually at some point during the loop's execution, the counter will be incremented to the value of 4. When control moves back up to the while-loop condition, the condition will evaluate to true (counter <= 4 is still true when counter has a value of 4). The body of the loop will execute one more time: The value of counter (4) will be printed and the counter will then be incremented to 5.

After the counter is incremented to 5, control moves back up to the while-loop condition. At this point, the condition counter <= 4 is false, since counter is 5, and the value 5 is not less than or equal to 4. The loop terminates and control moves to the print statement that appears after the loop. This statement prints the value "Done!" on the screen and the program is finished.

The trace chart below shows the rest of the variable values and the output of this code.

Statement
Executed
Value of
counter
Value of
number
counter <=
number?
Output
Shown
int number = 4;   4    
int counter = 1; 1      
while (counter <= number) {     true  
System.out.print(counter + " ");       1
counter++; 2      
while (counter <= number) {     true  
System.out.print(counter + " ");       1 2
counter++; 3      
while (counter <= number) {     true  
System.out.print(counter + " ");       1 2 3
counter++; 4      
while (counter <= number) {     true  
System.out.print(counter + " ");       1 2 3 4
counter++; 5      
while (counter <= number) {     false  
System.out.println("\nDone!");       1 2 3 4
Done!

The key thing to note as you look at the results is that the counter variable does actually get incremented one last time before the loop condition is false. The counter gets incremented to 5 after the value 4 is printed (which is the highest value the user wanted to count to). The loop condition still has to be checked, however. Just because the counter has been assigned a value of 5 doesn't mean the program knows to end the loop! The loop condition must first be evaluated - this is how the computer knows when to end the loop. When the condition is determined to be false, then the flow of execution can move down to the statement after the loop.

Note that if you have more than one statement in the body of your loop, you will need to enclose the statements in braces. But if your loop has exactly one statement inside the loop body, you can leave off the braces:

while (count <= 5)
    System.out.println(count++);
System.out.println("This statement is after the loop.");

Just make sure you pay attention to the logic of your loops if you leave off the braces. When you start nesting loops and other structures, this can cause problems if you're not careful.

Another thing to be careful of is how you write your loop expression. For example, what does this loop output?

public class NeverExecutes {

    public static void main(String[] args) {

        int x = 5;
        while (x < 5) { 
            System.out.println(x);
            x--;
        }
    }
}

Because x starts with a value of 5, the while-loop's condition is false as soon as the loop begins. This means the code block is never entered, it never executes.

Keep in mind that the condition on a while loop specifies the conditions under which the loop continues. The loop continues as long as the condition remains true; in other words, the loop terminates when the condition is false.

Exercises

1. Examine each of the loop headers below, particularly the loop condition. Under what conditions does the loop terminate? For example, if the loop was while (foo == 5), the loop would terminate when foo became equal to a value that is not 5.

  1. while (recCount != 10)
  2. while (userInput.equals(""))
  3. while (x >= 5)
  4. while (x < 5)
  5. while ( (x < 5) && (y > 10) )

2. Go back to the example that printed from 1 to 4:

public class LoopThis {

    public static void main(String[] args) {

        int number = 4
        int counter = 1;
        while (counter <= number) {
            System.out.print(counter + " ");
            counter++;
        }
        System.out.println("\nDone!");
    }
}

How would you modify this program so that the output appears instead as:

1
  2
  3
  4
  Done!

3. What is the output of the following code segment?

int counter = 1;
int sum = 0;
while (counter <= 5)
    sum += counter++;
System.out.println(sum);

4. What's wrong with the following program?

public class LoopProblem {
    public static void main(String[] args) {

        // print from 1 to 10 by 2's
        int counter = 1;
        while (counter != 10) {
            System.out.println(counter);
            counter += 2;
        }
    }
}

5. a. Write a loop that prints the numbers from 1 to 10 with their squares, like this:

1		1
2		4
3		9
4		16
5		25
6		36
7		49
8		64
9		81
10		100

5. b. How would you make the loop do the same output backwards (from 10 to 1)?

6. Write a while loop that counts from 1 to 20 by 2's on one line:

2 4 6 8 10 12 14 16 18 20

7. What is the output of each of the following loops?

Example 1:
int count = 4;
while (count > 0) {
    System.out.println(count);
    count--;
}
Example 2:
int count = 1;
while (count < 5) {
    System.out.println(count);
    count++;
}
Example 3:
int count = 3;
while (count <= 1) {
    System.out.println(count);
    count++;
}
Example 4:
int count = 3;
while (count >= 1) {
    System.out.println(count);
    count--;
}
System.out.println(count);
Example 5:
int count = 9;
while (count <= 10 && count > 4) {
    System.out.println(count);
    count--;
}
Example 6:
int x = 1, y = 3;
while (x < 5 || y > 0) {
    System.out.println(x++ + ", " + --y);
}   
System.out.print("x: " + x);
System.out.println(" y:" + y);

1. Examine each of the loop headers below, particularly the loop condition. Under what conditions does the loop terminate?

  1. while (recCount != 10)
    when recCount contains the value 10)
  2. while (userInput.equals(""))
    when the userInput String object contains characters (when it isn't empty)
  3. while (x >= 5)
    when x's value becomes less than 5
  4. while (x < 5)
    when x's value becomes 5 or more
  5. while ( (x < 5) && (y > 10) )
    when x's value becomes 5 or more OR when y's value becomes 10 or less

2. How would you modify the sample program so that the output appears instead as:

1
2
3
4
Done!

Solution: Change the print() inside the loop to a println().

3. What is the output of the following code segment?

int counter = 1;
int sum = 0;
while (counter <= 5)
      sum += counter++;
System.out.println(sum);

Solution:
15

4. What's wrong with the following program?

public class LoopProblem {
    public static void main(String[] args) 
    {
        // print from 1 to 10 by 2's
        int counter = 1;
        while (counter != 10) {
            System.out.println(counter);
            counter += 2;
        }
    }
}

Solution: You have an endless loop because counter will never be equal to 10.

5. a. Write a loop that prints the numbers from 1 to 10 with their squares.

Solution:

public class Question5a {
  
    public static void main(String[] args) {

        int counter = 1;  // init counter

        // while counter is 10 or less
        while (counter <= 10) {

              // print counter and its square
              System.out.printf("%d %10d%n", counter, Math.pow(counter));
              counter++;   // next counter
        }
    }
}

5. b. How would you make the loop do the same output backwards (from 10 to 1)?

Initialize the counter to 10
Change the loop condition to counter >= 1
Change the increment to a decrement (counter--)

public class Question5b {
  
    public static void main(String[] args) {

        int counter = 10;  // init counter

        // while counter 1 or more
        while (counter >= 1) {

              // print counter and its square
              System.out.printf("%d %10d%n", counter, Math.pow(counter));
              counter--;   // next counter
        }
    }
}

6. Write a while loop that counts from 1 to 20 by 2's on one line:

2 4 6 8 10 12 14 16 18 20
public class Question6 {
  
    public static void main(String[] args) {

        int counter = 2;
        while (counter <= 20) {
              System.out.printf("%d ", counter);
              counter += 2;
        }
    }
}

This will work, too:

public class Question6 {
  
    public static void main(String[] args) {

        int counter = 0;
        while (counter < 20) {
              counter += 2;
              System.out.printf("%d ", counter);
        }
    }
}

7. What is the output of each of the following loops?

Example 1:

4
  3
  2
  1

Example 2:

1
  2
  3
  4

Example 3:
(no output)

Example 4:

3
  2
  1
  0

Example 5:

9
  8
  7
  6
  5

Example 6:

1, 2
  2, 1
  3, 0
  4, -1
  x: 5 y:-1

Do-While Loops

A do-loop or do-while loop is often referred to as a post-test loop or bottom-checking loop because the condition that checks for loop continuation is at the bottom of the loop, instead of the top. Here's the general syntax of a do-while loop:

do {
	// statement 1
	// statement 2
	// etc...
} while (loop-continuation-condition);

Note the syntax carefully - there is a semi-colon after the while condition. This is because the braces of a do-while loop enclose the loop body, but not the while clause in the loop. Since the while clause appears after the closing brace, it requires a line-terminator (semi-colon) so that Java knows where the end of the while statement is.

Let's work through a do-while loop so we can understand how it works:

public class BasicLoop {

    public static void main(String[] args) {

        int count = 1;
        do {
            System.out.println(count + ":  Hello!");
            count++;
        } while (count <= 4);
        System.out.println(count + ":  Done!")
    }
}

The code above shows the BasicLoop example from earlier in the lesson as a do-while loop instead of a while-loop. Trace the code and then try it out, and you'll see it performs the exact same task as the earlier example.

While-Loop vs Do-While-Loop

The key difference between a while-loop and a do-while loop is that a while loop, a top-checking or pre-test loop, checks the condition of the loop before executing the loop body. The do-while loop, a bottom-checking or post-test loop, checks the condition of the loop after executing the loop body.

What does this mean? It means that the body of a while-loop might never execute, whereas the body of a do-while-loop is always guaranteed to execute at least once. See the following examples:

Example A: a while-loop

What is the output of the following program?

public class LoopProblem {
    public static void main(String[] args) {
        
        int counter = 1;
        while (counter > 1) {
            System.out.println(counter);
            counter--;
        }
    }
}

In the program above, we first initialize counter to 1. Then we begin the loop: check the condition counter >= 1. The condition is false, because counter is 1, and 1 is not >= 1, so the loop ends right away and no output is printed.

Example B: a do-while loop

What is the output of the following program?

public class LoopProblem {
    public static void main(String[] args) {
        
        int counter = 1;
        do {
            System.out.println(counter);
            counter--;
        } while (counter > 1);
    }
}

First, we encounter the do keyword, which indicates we are about to enter a bottom-checking (or post-test) do-while-loop.

The body of the loop prints the current value of counter (1) and then decrements counter. The counter variable now has a value of 0. The body of the loop has finished executing and now we move to the while and check our condition.

counter >= 1 is false, because counter (0) is not >= 1. So the loop now terminates, and the output of this program was just "1".

We can clearly see that these loops are the same, except that one checks the condition at the top and one checks the condition at the bottom. In both loops, the condition counter >= 1 was false the first time it was checked however, because the while loop checks the condition before the loop body is executed, the body of the loop never executes. Because the do-while loop checks the same condition after the loop body is executed, the body of the loop executes once before it is determined that the condition is false.

This summarizes what we said about the difference between pre-test loops and post-test loops: The body of a pre-test loop might never execute if the condition is false right away, whereas the body of a post-test loop is always guaranteed to execute at least once.

Exercises

1. What's the output of each of the following code segments:

Example 1:
int count = 4;
do {
  System.out.println(count);
  count--;
} while (count > 0);
Example 2:
int count = 9;
do {
  System.out.println(count);
  count--;
} while (count <= 10 && count > 4);
System.out.println(count);
                            
Example 3:
int count = 1;
do {
  System.out.println(count);
  count--;
} while (count > 1);

2. a. Write a program that requests a final grade. Use a do-loop to request the grade continuously as long as the grade entered is invalid. A grade is invalid if it is less than 0 or greater than 100. After a valid grade is entered, display it on the screen.

2. b. Modify the above program so that the user can cancel by entering the value 999.

2. c. Modify the program in 1. a. so that the user has only 5 tries to enter the grade. After 5 tries, the program terminates.

1. What's the output of each of the following code segments:

Example 1:

4
3
2
1

Example 2:

9
8
7
6
5
4

Example 3:

1

Question 2a:

solution 2a
Question 2. a) enter valid grade

Question 2b:

solution 2b
Question 2. b) enter valid grade

Question 2c:

solution 2c
Question 2. c) enter valid grade

Priming Read / Continuing Read

The priming read / continuing read is a common pattern you see in programs that use loops. It is often used to validate user inputs (although that's not the only time it's used), for example, say you want to ask the user for a positive number between 1 and 100, and you want to keep on asking repeatedly until they follow your instructions and enter a valid number:

import java.util.Scanner;

public class PrimingRead {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);

        int number = 0;  // why do we have to declare this here?
        do {
            System.out.print("Enter a number between 1 and 100, inclusive: ");
            number = in.nextInt();
        } while (number < 1 || number > 100);

        System.out.printf("You entered %d\n", number);
    }
}

Try this program in your editor and run it. What happens when you type -3? What happens when you type 333? Then type 33. The program should run until you enter the valid value of 33:

Enter a number between 1 and 100, inclusive: -3
Enter a number between 1 and 100, inclusive: 333
Enter a number between 1 and 100, inclusive: 33
You entered 33

The program works as we have intended! However, it's not enough to write nice code that works and is efficient. Your program also has to be user-friendly!

What if your user doesn't understand your instructions, or what if they are one of those users that doesn't really read things well? When they run the program and enter invalid data, it actually looks like they are entering several numbers - it doesn't tell them that they're doing something wrong, and that the program is asking repeatedly so it can get a correct value. This is NOT good programming.

To make the program more user friendly, we should give the user a good error message... something like "Error: You must enter a value between 1 and 10." There are a few ways to do this. Some people choose to put an if-statement inside the loop, but it's not the best solution:

import java.util.Scanner;

public class PrimingReadBad {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);

        int number = 0;  // why do we have to declare this here?
        do {
            System.out.print("Enter a number between 1 and 100, inclusive: ");
            number = in.nextInt();
            if (number < 1 || number > 100)
                System.out.println("Error: You must enter a value between 1 and 10.");
        } while (number < 1 || number > 100);

        System.out.printf("You entered %d\n", number);
    }
}

There are SO MANY THINGS WRONG with this program!

A better solution is to use the priming read / continuing read pattern. This pattern allows you to ask the user for their input first. Then you start a top-checking loop that performs the validation of the user input:

import java.util.Scanner;

    public class PrimingReadGood {

        public static void main(String[] args) {

        Scanner in = new Scanner(System.in);

        // this is the "priming read" - it primes the number variable
        // by reading the user's first try at inputting a value
        System.out.print("Enter a number between 1 and 100, inclusive: ");
        int number = in.nextInt(); 

        while (number < 1 || number > 100) {
              System.out.println("Error: You must enter a value between 1 and 10.");

              // this is the "continuing read" - it asks the user for the input
              // again, allowing the loop to continue executing when needed
              System.out.print("Enter a number between 1 and 100, inclusive: ");
              number = in.nextInt();
        }

        System.out.printf("You entered %d\n", number);
    }
}

What this code does is it "primes" the number variable with the user's first try at inputting a value. Then it uses a top-checking loop to see if that number is valid or not. If the condition is true, the user's input is invalid, so it gives the user the error message and prompts them for a new number. The read inside the loop is the "continuing read" - it's what allows the loop to continue executing normally, by allowing the user to change the value of the number variable. As long as the user keeps entering invalid values, the loop will continue to execute:

Enter a number between 1 and 100, inclusive: -3
Error: You must enter a value between 1 and 10.
Enter a number between 1 and 100, inclusive: 333
Error: You must enter a value between 1 and 10.
Enter a number between 1 and 100, inclusive: 33
You entered 33

This version of the program is much more efficient and much clearer. And it does exactly what we want!

Exercise

Use the priming read / continuing read pattern in a program that calculates the user's average grade for the semester: The user enters their final grades for each of their courses, and the program adds them to a total. After the loop terminates, the average grade is calculated and displayed.

Students can take any number of courses, so we don't know how many courses to ask for. To deal with this, we will tell the user to enter a negative grade (anything less than 0) when they're finished entering grades for their courses. This works, since we don't assign negative grades, anyway. Your program's loop should execute only as long as the user-entered final grade is not a negative value.

Test data and sample output:

Enter final grade #1 (negative number quits): 78.5
Enter final grade #2 (negative number quits): 79
Enter final grade #3 (negative number quits): 85.1
Enter final grade #4 (negative number quits): -5
Average Grade: 80.87
Enter final grade #1 (negative number quits): -1
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        
        double total = 0.0, average = 0.0;
        int numCourse = 0;
        
        System.out.printf("Enter final grade #%d (negative number quits): ", 
                numCourse + 1);
        double grade = in.nextDouble();
        
        while (grade >= 0) {
            numCourse++;
            total += grade;
            System.out.printf("Enter final grade #%d (negative number quits): ", 
                    numCourse + 1);
            grade = in.nextDouble();
        }
        
        if (numCourse > 0) {  // avoid divide by 0

            average = total / (numCourse);
            System.out.printf("Average Grade: %.2f\n", average);    
        }
    }
}

Exercises

1. For this program, use either a while-loop or a do-loop, whichever you think is most efficient. Write a program that records scientific test results (they'll have decimal values) from the user. As each test result is entered, add it to a total. After all the test results have been entered, display the total.

You don't know how many test results they'll enter, so after each result is entered, prompt the user with a question such as "Would you like to enter another test result? (Y/N)". The user can answer "Yes" or "No" too this question, or even just "Y" or "N". To capture this, we would use the Scanner's next() method to grab only the first word of the user input:

String answer = in.next();

However, we can make this program more efficient if we use a character value instead of a string, and just compare the first letter of the user's input (Y or N). There is a method in the String class called charAt(index). You give charAt() a string index (the position number, where the first character is position 0, the second position 1, etc) of the character you'd like to have and it will return that character at the specified index as a char value. For example:

"hello".charAt(0) // returns 'h'
"hello".charAt(1) // returns 'e'
"hello".charAt(2) // returns 'l'
"hello".charAt(4) // returns 'o'
"hello".charAt(5) // would give an error because there is no index 5

So since we only what the first character that the user types, we can use:

char keepGoing = 'Y';  // initialize to yes
...  // code code code
keepGoing = in.next().charAt(0);

Next, we want to see if the user says 'Y' to our prompt, meaning they'd like to enter another test result. So our loop condition could be something like keepGoing == 'y' || keepGoing == 'Y' because we don't know if the user will type an upper-case or a lower-case answer. If you prefer, you can use one of the String class's methods toUpperCase() or toLowerCase() to convert the user's answer to upper- or lower-case, and then compare. For example, I will use upper-case comparisons:

keepGoing = in.next().toUpperCase().charAt(0);

Then my loop condition would be keepGoing == 'Y'.

Add this functionality to your program, so your user can enter as many test results as they'd like.

Question 1 (do-while-loop):

question 1 do while loop
Question 1. total results (do-while-loop)

Question 1 (while-loop):

question 1 while loop
Question 1. total results (while)