Menu
Kevin's Guides
Decorative intro photo for: Chapter 7: Loops

Chapter 7: Loops

Write a comment

Chapter 7: Loops

Being able to do the same types of tasks or computations repeatedly is one of the most useful things we can do with computers. Loops are blocks of code that can be repeated until a certain condition is met. They are fundamental to the development of many algorithms. There are several loop structures, which we will cover in this chapter.


7.1 For Loops

A for loop is a type of loop that allows us to repeat code given some type of sequential condition. The structure of a for loop looks like this:

overview diagram of a for loop

A for loop starts with a control variable which keeps track of which increment of the loop we're at. For example, if we want the loop to repeat five times, the control variable might be initialized with a value of 1 and end with a value of 5. This is the starting point in this control. It could look something like int i = 0;

You will commonly see int i used as the control variable, this is just convention. It stands for the index or iteration of the loop. You can use any variable identifier you'd like, but i is most common.

The loop condition is the condition that must be met for the loop to be over. For example, if we were looping 1 through 5, the condition might be i <= 5; Once this condition is satisfied (i is no longer less than or equal to 5) the loop stops.

The last part of creating a for loop is the increment (or decrement) of the loop. The increment specifies how much the control variable should change between each iteration of the loop. If we're going from 1 to 5, the increment would be to add one. So it might look like i++; or i = i + 1;

When we put all this together, we can create a loop that iterates over the number 1 through 5 using the following code. The body of the loop in this example simply prints the current loop index to the screen each time the loop body is executed.

    public static void main(String[] args) {
        //simple for loop iterating from 1 to 5
        for(int i = 1; i <= 5; i++){
            //print out i
            System.out.println(i);
        }
    }
1
2
3
4
5

A Common Mistake in Loop Condition

It's not uncommon for people to forget that once the condition of the loop is no longer true, the loop does not execute the body of the loop. For example, if you want to iterate over the numbers 1 through 5, you might be tempted to write something like this:

    public static void main(String[] args) {
        //simple for loop iterating from 1 to 5
        for(int i = 1; i < 5; i++){
            //print out i
            System.out.println(i);
        }
    }
1
2
3
4

Since the loop only executes while the condition is satisfied, the above code will only output the numbers 1 through 4, not 1 through 5. Once the control variable reaches 4 in this case, the next increment is 5. 5 is not less than 5, so 5 does not get printed to the screen.

To get around this, we added the <= conditional operator, so it executes one more time while i is equal to 5. Alternatively, to print the numbers 1 through 5, we could have use a condition of x<6.

Always check your loop and make sure you're thinking about this, so you don't run into logic errors.


Knowledge Check: Decrement Loop

Given what you know about for loops, create a loop that prints the numbers 10 through 1 to the screen, in decreasing order, using a decrement of 1 each time.

Sample Output:

10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
        for(int i = 10; i > 0; i--){
            System.out.print(i + ", ");
        }

7.1b: Factorial Calculator Example

For the next example, with for loops, we're going to be creating a method that calculates a factorial. A factorial is a math function that calculates a number multiplied by all the numbers coming before it. It is represented in math with an exclamation mark after a number. For example, 3! (pronounced 3 factorial) would be \(3*2*1=6\). So \(3! = 6\). Next, \(4!\) would be \(4*3*2*1=24\) and so on.

Let's start by creating a static method that takes an integer value as its parameter, and returns an integer with the factorial result. I've chosen to call it the getFactorial method.

    static int getFactorial(int x){
        //find factorial
    }

To find the factorial, we're going to have to create a for loop and use some variables to keep track of things. Since we're just multiplying, it doesn't matter if we start the loop from 1 and increase or from the highest number and decrease. I've decided to start from 1 and iterate through to x, the number we're getting the factorial for. I've also decided to initialize a variable called result to keep track of the result. I'm starting it at 1 and each time the loop executes, I'm going to multiply it by the next number in the sequence.

    static int getFactorial(int x){
        
        //the running factorial result
        int result = 1;

        //iterate from 1 through x, incrementing loop by 1 each time
        for(int i = 1; i <= x; i++){
            //multiply the result by i, the next number in the sequence
            result = result * i;
        }
        return result;
    }

To test out this method, I've added a single line to the main method that prints the factorial of 3, which I know to be 6.

    public static void main(String[] args) {

        System.out.println(getFactorial(3));

    }
6

Excellent, that worked. The first time the loop was executed, result was 1 and i was 1, so result kept a value of 1. The second time the loop executed, i was now equal to 2, 2 was multiplied by result (1) for a value of 2. Now result is equal to 2. On the third iteration, i was equal to 3 and result was still equal to 2 from before. Once multiplied, result is equal to 6. The loop ends and returns a value of 6.

One test is not sufficient to prove that code is working right. You should always check your code by testing multiple values that you know the answer to. Since we know 4! is 24, let's see what happens when I try finding the factorial of 4 with my code.

    public static void main(String[] args) {

        System.out.println(getFactorial(4));

    }
24

Great! It seems to be working.

Now that I'm fairly confident my algorithm is working right, let's try a bigger number, like 10!.

    public static void main(String[] args) {

        System.out.println(getFactorial(10));

    }
3628800

Excellent, this is also correct. But what happens if I try to calculate a much larger number, like 100 factorial?

    public static void main(String[] args) {

        System.out.println(getFactorial(100));

    }
0

It said the result is zero! That's not right. It should be a number much larger than that. Why did this happen? Recall in chapter 3 that ints are 32 bit primitive data types. That means they can only store a maximum number of (2^31)-1 (which is 2,147,483,647). Although 2 billion seems like a pretty big number, when we're doing factorials, numbers get incredibly large incredibly fast. 100! is well beyond the scope of what can be calculated using an integer. To fix this, we can change the data type of the result and the method from integer to double. Let's see what happens when we do this:

public class Main {

    public static void main(String[] args) {

        System.out.println(getFactorial(100));

    }

    static double getFactorial(double x){

        //the running factorial result
        double result = 1.0;

        //iterate from 1 through x, incrementing loop by 1 each time
        for(int i = 1; i <= x; i++){
            //multiply the result by i, the next number in the sequence
            result = result * i;
        }
        return result;
    }
    
}
9.33262154439441E157

Now I got an answer of roughly 9.332E157, that means \(9.332\times10^{157}\). The number's so large it had to use scientific notation! This, however, is correct. We have lost some accuracy with rounding using doubles (we don't know the exact value down to 157 digits), but we have a pretty close approximation.


7.2: While Loops

While loops are loops which iterate through a block of code while some condition is true. They are simpler than for loops, in that there's only one statement at the start of a while loop. The loop will continue executing until a certain specified condition is met. This means to get out of the loop, eventually we have to reach a point where the specified condition will be false. If the loop is always true, we will have an infinite, never-ending loop. Infinite loops will usually result in the program crashing, or at the very least, doing some unexpected behaviors.

The structure of a while loop is as follows:

overview diagram of a while loop in java

You may visualize it with this flow chart.

flow of a while loop with condition checking diagram

We can use while loops to increment through numbers similar to how we did in the earlier for-loop example, when we iterated between the numbers 1 and 5. Ultimately, it is up to you to decide if a for loop or a while loop is better. If you know that you're going to increment the control variable by a set amount each time, for a set number of events, a for loop is probably better. If you don't know exactly where the end point will be, a while loop may serve you better.

The code below uses a while loop to print the numbers 1 through 5 out to the screen.

    public static void main(String[] args) {

        //set i to 1
        int i = 1;

        //while i is less than/equal to 5
        while(i<=5){
            //print out i
            System.out.println(i);
            //increment i by 1
            i++;
        }
        //at this point, i must be greater than 5, so the loop has exited
        System.out.println("Loop has exited");

    }
1
2
3
4
5
Loop has exited

Note that I initialized the variable i before the loop started. If I tried to initialize it in the loop body, it would not work. Whatever setup required for the condition must come before the loop starts. If any variables are initialized in the loop body, they are re-initialized each time the loop is executed (thrown out and start anew). If I failed to increment i by 1 in the loop's body, it would have resulted in an infinite loop. These are just some things to keep in mind.

Conditional Exit Based on Prompt

Here's an example of a loop that could run an infinite amount of times, until a certain exit condition is met. For this example, the user will be asked to type a string of text. Each time they enter a string,  the loop runs again and adds that to an existing string. When they type "exit" the program prints out the combined string, and the program is done.

Combined Message Maker
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {

        //initialize scanner
        Scanner input = new Scanner(System.in);

        //String to store value
        String comboString = "";

        //String to store what the user enters
        String userTyped = "";

        //while the message they typed isn't equal to "exit"
        while(!userTyped.equals("exit")){
            //add the last userTyped message to the longString
            comboString = comboString + userTyped;
            //Have them enter some more text
            System.out.println("Please enter some text. Type exit when done.");
            userTyped = input.nextLine();
        }

        //close scanner and print result
        input.close();
        System.out.println("Your combined string is: " + comboString);

    }

}
Please enter some text. Type exit when done.
hello
Please enter some text. Type exit when done.
world
Please enter some text. Type exit when done.
i'm
Please enter some text. Type exit when done.
kevin
Please enter some text. Type exit when done.
exit
Your combined string is: helloworldi'mkevin

Note in the above example on line 19, I combined the strings before taking the next string. The first time the loop runs it combines nothing with nothing, so that's fine. The second time, it combines nothing with the first word (or words) the user entered. Each time after, it combines the comboString with whatever they type next. I did this at the start of the loop body, because if I did it at the end, it's possible the user could have typed "exit" and then the string "exit" would have been added to the end of the printed message. In other words, it would have said "helloworldi'mkevinexit" instead of "helloworldi'mkevin"

Recall chapter 4 when we talked about the different ways Java compares objects and values. On line 17 where I checked if the message was "exit" we have to use the equals method, not the == operator. If we use the == operator or != operator, Java will say "no, these aren't the same string." To check by value, we must use the String.equals() method.


Breaking Out Of Loops

There are other ways to exit a loop, outside of the predefined condition. If we have multiple conditions, or we just want to structure our loop differently, we can use the break keyword to end the loop at any time and "break out" of it.

Take a look at the following code which has a while loop that's always true. We can end it whenever we want using a break statement.

    public static void main(String[] args) {

        int i = 0;
        while (true){
            i = i + 1;
            System.out.print(i +", ");
            if (i==10){
                break;
            }
        }

    }
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
Process finished with exit code 0

Since the condition above is always true, the while loop would execute forever (or until the system runs out of memory or encounters an error). With the break when i==10, the loop exits at this point, and no further numbers are printed to the screen.

You can break out of for loops early as well, if you'd like.

        for(int i = 1; true; i++){
            System.out.print(i + ", ");
            if(i==10){
                break;
            }
        }
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
Process finished with exit code 0

Do While Loops

Do while loops are another loop structure that places the code block to be executed before the condition. This is the opposite placement of the regular while loop, which places the condition before the statements to execute in the loop body. This means the code in a do while loop will always be executed at least once, before checking to see if it should be executed again.

The structure of a do-while loop is as follows.

structure of a do while loop in java
        do{
            //stuff to do
        } while(some condition);

A visual flow looks like this:

flow of a do while loop in java diagram

Simple Example

A simple example of a do while loop is below. The condition is always false, so it never loops a second time. If you run it, you see that the code in the do block still gets executed the first time:

    public static void main(String[] args) {

        do{
            System.out.println("Hello, World.");
        } while(false);

    }
Hello, World.

If you change the condition from false to true, the loop will run infinitely, until your computer runs out of memory.

You're probably getting tired of seeing hello world by now! I'll try to make this the last time I use it as an example in this series.


Nested Loops

In the same way we can nest conditional statements inside other conditional statements, we can nest loops within other loops. This allows us to iterate through multiple sets of values at the same time. Take columns and rows in a grid for example. We could loop through each row and each column to print out a square of any size. That's what we're going to be looking at in this example.

The character I have chosen to represent a block in our printed square will be a digit symbol or hash tag #.

Since we print to the console one row at a time, and there's no way to go back and add more to a row later, we're going to use each row as the outer loop. The inner loop will print out the specified number symbols in each row - to make the "columns" of the grid. Say for example we want a 4x4 square. The outer loop starts with the first row, the inner loop prints out 4 symbols, then the outer loop repeats itself for the second row, the inner loop prints four symbols, the third and fourth row do the same thing in the outer loop, and then the program exits.

        //outer loop iterates through rows 1-4
        for(int a = 1; a<5; a++){
            //inner loop prints each row
            for(int b = 1; b < 5; b++){
                System.out.print("#");
            }
            System.out.println();
        }
####
####
####
####

Now we have code that can print out a 4x4 square. We can easily modify it to print out a bigger or smaller square as needed. If we wanted to print a 16x16 grid of symbols, all we'd have to do is change the condition from < 5 to < 17.

Here is an example of doing the same thing with a while loop:

        //initialize variables
        int a = 1; int b = 1;
        
        //outer loop iterates through rows 1-4
        while(a < 5){
            //inner loop iterates through columns
            while (b < 5){
                System.out.print("#");
                b++;
            }
            System.out.println();
            //b must be set back to 1 after each inner loop completes
            b=1;
            a++;
        }
####
####
####
####

Note that on line 13, we have to reset b to 1. If we do not, the last time the loop runs for the first row, b is equal to 5, and stays equal to 5 for the second row, so nothing is printed on the second, third, or fourth row.

An alternative to setting b to 1 on line 13 would be to initialize the variable b within the body of the outer loop, with a value of 1. Then, each time the outer loop runs, b is reinitialized with a value of 1.

        //initialize variable
        int a = 1;

        //outer loop iterates through rows 1-4
        while(a < 5){
            //initialize b inside the outer loop
            int b = 1;

            //inner loop iterates through columns
            while (b < 5){
                System.out.print("#");
                b++;
            }
            System.out.println();
            a++;
        }
####
####
####
####

Ch. 7 Assignment: Frame Printer

For the assignment in this chapter, create a program that asks the user to enter two numbers. The first for number of rows and the second for number of columns. Disregard frames under 3x3 in size. The center of the frames should be blank. Create the tops and bottoms of each frame using the horizontal dash - character and the sides using the vertical bar | character. The area between the top, bottom, and sides, should be blank (empty spaces). Print the frame from a second method, outside the main method, that takes the integers the user typed as parameters to create the frame.

Hints:

  • The method that prints the frame should look something like this: static void printFrame(int width, int height)
  • You can get the next integer the user types using the scanner's nextInt() method.
  • There are multiple ways to go about doing this. In my solution, I'll be using for loops.
  • It may make sense to print the top of the frame, then print the rows between top and bottom, then print the bottom of the frame the same way you printed the top.
  • It may be helpful to create a variable to keep track of the amount of spaces you need to print between the sides of the frame

Here is a sample of what my program looks like when done:

Enter a width:
6
Enter a height:
4
------
|    |
|    |
------
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {

        //create scanner
        Scanner input = new Scanner(System.in);

        //get user input
        System.out.println("Enter a width:");
        int width = input.nextInt();

        System.out.println("Enter a height:");
        int height = input.nextInt();

        //close scanner
        input.close();
        
        //print the frame using our printFrame method
        printFrame(width, height);

    }

    /**
     * 
     * @param width - the width of the frame
     * @param height - the height of the frame
     */
    static void printFrame(int width, int height){

        //print the top of the frame
        for(int i = 0; i < width; i++){
            System.out.print('-');
        }
        //print a new line after the top is done
        System.out.println();

        //print the rows with "sides" of the frame
        int numberOfSideRows = height - 2;
        int numberOfSpaces = width - 2;
        for(int i = 0; i < numberOfSideRows; i++){
            //print the left side of the row
            System.out.print('|');
            //print the right amount of spaces
            for(int spaces = 0; spaces < numberOfSpaces; spaces++){
                System.out.print(' ');
            }
            //print the right side of the row
            System.out.print('|');
            //print a new line after each row
            System.out.println();
        }
        //print the bottom of the frame
        for(int i = 0; i < width; i++){
            System.out.print('-');
        }

    }

}
Write comments...
You are a guest ( Sign Up ? )
or post as a guest
Loading comment... The comment will be refreshed after 00:00.

Be the first to comment.

Related Guides

Chapter 8: Recursion
Learn how to use recursive loops in Java and understand the performance impact they may have on time and memory.
Chapter 13: Exception Handling - Preventing Errors
Learn how to handle common exception types with try/catch blocks.
Chapter 4: Decision Making with Control Statements
You will learn how to use control statements (If/Else/Switches) to make decisions in Java. You'll also learn about the equals method and build a tax calculator.
Chapter 1: Introduction to Java
This section discusses key components of computers and how the Java programming language works. You will also learn about the tools developers use to code.
Chapter 3: Variables, Scanners & Strings
This chapter explains core Java concepts such as variables, data types, strings, and scanners to read user input.
Chapter 2: Hello, World.
This section introduces you to the IntelliJ IDE and your first Java project, which is called "Hello, World."
Main Menu
Kevin's Guides
Full size image will appear here.