Main Page

Previous Next

Loops

A loop allows you to execute a statement or block of statements repeatedly. The need to repeat a block of code arises in almost every program. If you did the first exercise at the end of the last chapter, based on what you had learned up to that point you would have come up with a program along the lines of:

public class TryExample1_1 {
  public static void main(String[] args) {
    byte value = 1;
    value *= 2;
    System.out.println("Value is now "+value);
    value *= 2;
    System.out.println("Value is now "+value);
    value *= 2;
    System.out.println("Value is now "+value);
    value *= 2;
    System.out.println("Value is now "+value);
    value *= 2;
    System.out.println("Value is now "+value);
    value *= 2;
    System.out.println("Value is now "+value);
    value *= 2;
    System.out.println("Value is now "+value);
    value *= 2;
    System.out.println("Value is now "+value);
  }
}

The same pair of statements has been entered eight times. This is a rather tedious way of doing things. If the program for the company payroll had to include separate statements for each employee, it would never get written. A loop removes this sort of the difficulty. We could write the method main() to do the same as the code above as:

public static void main(String[] args) {
  byte value = 1;
  for (int i=0; i<8 ; i++) {
    value *= 2;
    System.out.println("Value is now " + value);
  }
}

The for loop statement causes the statements in the following block to be repeated eight times. The number of times it is to be repeated is determined by the stuff between parentheses following the keyword for – we will see how in a moment. The point is you could, in theory, repeat the same block of statements as many times as you want – a thousand or a million – it is just as easy and it doesn't require any more lines of code. The primary purpose of the for loop is to execute a block of statements a given number of times.

There are three kinds of loop statements you can use, so let's look at these in general terms first:

  1. The for loop:

    for (initialization_expression ; loop_condition ; increment_expression) {
      // statements
    }
    

    The control of the for loop appears in parentheses following the keyword for. It has three parts separated by semi-colons.

    The first part, the initialization_expression, is executed before execution of the loop starts. This is typically used to initialize a counter for the number of loop iterations – for example i = 0. With a loop controlled by a counter, you can count up or down using an integer or a floating point variable.

    Execution of the loop continues as long as the condition you have specified in the second part, the loop_condition, is true. This expression is checked at the beginning of each loop iteration, and when it is false, execution continues with the statement following the loop block. A simple example of what the loop_condition expression might be is i<10, so the loop would continue in this case as long as the variable i has a value less than 10.

    The third part of the control information between the parentheses, the increment_expression, is usually used to increment the loop counter. This is executed at the end of each loop iteration. This could be i++, which would increment the loop counter, i, by one. Of course, you might want to increment the loop counter in steps other than 1. For instance, you might write i += 2 as the increment_expression to go in steps of 2, or even something more complicated such as i = 2*i+1.

  2. The while loop:

    while (expression) {
      // statements
    }
    

    This loop executes as long as the given logical expression between parentheses is true. When expression is false, execution continues with the statement following the loop block. The expression is tested at the beginning of the loop, so if it is initially false, the loop statement block will not be executed at all. An example of a while loop condition might be, yesNo=='Y' || yesNo=='y'. This expression would be true if the variable yesNo contained 'y' or 'Y', so yesNo might hold a character entered from the keyboard in this instance.

  3. The do while loop

    do {
      // statements
    } while (expression);
    

    This loop is similar to the while loop, except that the expression controlling the loop is tested at the end of the loop block. This means that the loop block is executed at least once, even if the expression is always false.

    We can contrast the basic logic of the three kinds of loop in a diagram.

    Click To expand

This shows quite clearly that the only difference between the while loop and the do while loop is where the test is carried out.

Let's explore each of these in turn and see how they work in a practical context.

Try It Out – The for Loop

Let's start with a very simple example. Suppose you want to calculate the sum of the integers from 1 to a given value. You can do this using the for loop as in the following example:

public class ForLoop {
  public static void main(String[] args) {
    int limit = 20;                     // Sum from 1 to this value
    int sum = 0;                        // Accumulate sum in this variable

    // Loop from 1 to the value of limit, adding 1 each cycle
    for(int i = 1; i <= limit; i++) {
      sum += i;                        // Add the current value of i to sum
    }
    System.out.println("sum = " + sum);
  }
}

This program will produce the output,

sum = 210

but you can try it out with different values for limit.

How It Works

All the work is done in the for loop. The loop counter is i, and this is declared and initialized within the for loop statement. The syntax of the for loop is shown in the following diagram:

Click To expand

As you see, there are three elements that control the operation of a for loop, and they appear between the parentheses that follow the keyword for. In sequence their purpose is to:

  • Set the initial conditions for the loop, particularly the loop counter

  • Specify the condition for the loop to continue

  • Increment the loop counter

They are always separated by semi-colons.

The first control element is executed when the loop is first entered. Here we declare and initialize the loop counter i. Because it is declared within the loop, it will not exist outside it. If you try to output the value of i after the loop with a statement such as,

System.out.println("Final value of i = " + i);  // Will not work outside the loop

you will find that the program will not compile. If you need to initialize and/or declare other variables for the loop, you can do it here by separating the declarations by commas. For example, we could write:

for (int i = 1, j = 0; i <= limit; i++) {
  sum += i * j++;                      // Add the current value of i*j to sum
}

We initialize an additional variable j, and, to make the loop vaguely sensible, we have modified the value to add the sum to i*j++ which is the equivalent of i*(i-1) in this case. Note that j will be incremented after the product i*j has been calculated. You could declare other variables here, but note that it would not make sense to declare sum at this point. If you can't figure out why, delete the original declaration of sum and, put it in the for loop instead to see what happens. The program won't compile – right? After the loop ends the variable sum no longer exists, so you can't reference it.

The second control element in a for loop is a logical expression which is checked at the beginning of each iteration through the loop. If the expression is true, the loop continues, and as soon as it is false the loop is finished. In our program the loop ends when i is greater than the value of limit.

The third control element in a for loop typically increments the loop variable, as we have in our example. You can also put multiple expressions here too, so we could rewrite the above code fragment, which added j to the loop, as:

for (int i = 1, int j = 0; i <= limit; i++, j++) {
  sum+=i*j;                      // Add the current value of i*j to sum
}

Again, there can be several expressions here, and they do not need to relate directly to the control of the loop. We could even rewrite the original loop for summing integers so that the summation occurs in the loop control element:

for (int i = 1; i <= limit; sum += i, i++) {
  ;
}

Now the loop statement is empty – you still need the semi-colon to terminate it though. It doesn't really improve things though and there are hazards in writing the loop this way. If you forget the semi-colon the next statement will be used as the loop statement, which is likely to cause chaos. Another potential problem arises if you happen to reverse the sequence of adding to sum and incrementing i, as follows:

for (int i = 1; i <= limit; i++, sum += i) {  // Wrong!!!
  ;
}

Now you will generate the wrong answer. This is because the expression i++ will be executed before sum += i, so the wrong value of i is used.

You can omit any or all of the elements that control the for loop, but you must include the semi-colons. It is up to you to make sure that the loop does what you want. We could write the loop in our program as:

for(int i = 1; i <= limit; ) {
  sum += i++;                            // Add the current value of i to sum
}

We have simply transferred the incrementing of i from the for loop control to the loop statement. The for loop works just as before. However, this is not a good way to write the loop, as it makes it much less obvious how the loop counter is incremented.

Counting Using Floating Point Values

You can use a floating point variable as the loop counter if you need to. This may be needed when you are calculating the value of a function for a range of fractional values. Suppose you wanted to calculate the area of a circle with values for the radius from 1 to 2 in steps of 0.2. You could write this as:

for(double radius = 1.0; radius <= 2.0; radius += 0.2) {
  System.out.println("radius = " + radius + " area = " + Math.PI*radius*radius);
}

This will produce the output:

radius = 1.0 area = 3.141592653589793
radius = 1.2 area = 4.523893421169302
radius = 1.4 area = 6.157521601035994
radius = 1.5999999999999999 area = 8.04247719318987
radius = 1.7999999999999998 area = 10.178760197630927
radius = 1.9999999999999998 area = 12.566370614359169

The area has been calculated using the formula (r2 with the standard value PI defined in the Math class, which is 3.14159265358979323846. Although we intended the values of radius to increment from 1.0 to 2.0 in steps of 0.2, they don't quite make it. The value of radius is never exactly 2.0 or any of the other intermediate values because 0.2 cannot be represented exactly as a binary floating point value. If you doubt this, and you are prepared to deal with an infinite loop, change the loop to:

// BE WARNED - THIS LOOP DOES NOT END
for(double radius = 1.0; radius != 2.0; radius += 0.2) {
  System.out.println("radius = " + radius + " area = " + Math.PI*radius*radius);
}

If the value of radius reaches 2.0, the condition radius ! =2.0 will be false and the loop will end, but unfortunately it doesn't. Its last value before 2 will be approximately 1.999… and the next value will be something like 2.1999… and so it will never be 2.0. From this we can deduce a golden rule:

Important 

Never use tests that depend on an exact value for a floating point variable to control a loop.

Try It Out – The while Loop

We can write the program for summing integers again using the while loop, so you can see how the loop mechanism differs from the for loop.

public class WhileLoop {
  public static void main(String[] args) {
    int limit = 20;                     // Sum from 1 to this value
    int sum = 0;                        // Accumulate sum in this variable
    int i = 1;                          // Loop counter

    // Loop from 1 to the value of limit, adding 1 each cycle
    while(i <= limit) {
      sum += i++;                       // Add the current value of i to sum
    }
    System.out.println("sum = " + sum);
  }
}

You should get the result:

sum = 210

How It Works

The while loop is controlled wholly by the logical expression that appears between the parentheses that follow the keyword while. The loop continues as long as this expression has the value true, and how it ever manages to arrive at the value false to end the loop is up to you. You need to be sure that the statements within the loop will eventually result in this expression being false. Otherwise you have an infinite loop.

How the loop ends in our example is clear. We have a simple count as before, and we increment i in the loop statement that accumulates the sum of the integers. Sooner or later i will exceed the value of limit and the while loop will end.

You don't always need to use the testing of a count limit as the loop condition. You can use any logical condition you want.

And last, but not least, we have the do while loop.

Try It Out – The do while Loop

As we said at the beginning of this topic, the do while loop is much the same as the while loop, except for the fact that the continuation condition is checked at the end of the loop. We can write an integer summing program with this kind of loop too:

public class DoWhileLoop {
  public static void main(String[] args) {
    int limit = 20;                     // Sum from 1 to this value
    int sum = 0;                        // Accumulate sum in this variable
    int i = 1;                          // Loop counter

    // Loop from 1 to the value of limit, adding 1 each cycle
    do {
      sum += i;                         // Add the current value of i to sum
      i++;
    } while(i <= limit);

    System.out.println("sum = " + sum);
  }
}

How It Works

The statements within the loop are always executed at least once because the condition determining whether the loop should continue is tested at the end of each iteration. Within the loop we add the value of i to sum, and then increment it. When i exceeds the value of limit, the loop ends, at which point sum will contain the sum of all the integers from 1 to limit.

The loop statement here has braces around the block of code that is within the loop. We could rewrite the loop so that only one statement was within the loop, in which case the braces are not required. For instance:

    do
      sum += i;                          // Add the current value of i to sum
    while(++i <= limit);

Of course, you could still put the braces in if you want. I advise that you always use brackets in your loops even when they are only a single statement. There are often several ways of writing the code to produce a given result, and this is true here – we could also move the incrementing of the variable i back inside the loop and write it as:

    do
      sum += i++;                        // Add the current value of i to sum
    while (i <= limit);

Note the semi-colon after the while condition is present in each version of the loop. This is part of the loop statement so you must not forget to put it in. The primary reason for using this loop over the while loop would be if you want to be sure that the loop code always executes at least once.

Nested Loops

You can nest loops of any kind one inside another to any depth. Let's look at an example where we can use nested loops.

A factorial of an integer, n, is the product of all the integers from 1 to n. It is written as n!. It may seem a little strange if you haven't come across it before, but it can be a very useful value. For instance, n! is the number of ways you can arrange n different things in sequence, so a deck of cards can be arranged in 52! different sequences. Let's try calculating some factorial values.

Try It Out – Calculating Factorials

Our example will calculate the factorial of every integer from 1 up to a given limit. Enter the following code with the two for loops:

public class Factorial {
  public static void main(String[] args) {
    long limit = 20;        // to calculate factorial of integers up to this value
    long factorial = 1;     // factorial will be calculated in this variable

    // Loop from 1 to the value of limit
    for (int i = 1; i <= limit; i++) {
      factorial = 1;        // Initialize factorial

      for (int factor = 2; factor <= i; factor++) {
        factorial *= factor;
      }
      System.out.println(i + "!" + " is " + factorial);
    }
  }
}

This program will produce the output:

1! is 1
2! is 2
3! is 6
4! is 24
5! is 120
6! is 720
7! is 5040
8! is 40320
9! is 362880
10! is 3628800
11! is 39916800
12! is 479001600
13! is 6227020800
14! is 87178291200
15! is 1307674368000
16! is 20922789888000
17! is 355687428096000
18! is 6402373705728000
19! is 121645100408832000
20! is 2432902008176640000

How It Works

The outer loop, controlled by i, walks through all the integers from 1 to the value of limit. In each iteration of the outer loop, the variable factorial is initialized to 1 and the nested loop calculates the factorial of the current value of i using factor as the control counter that runs from 2 to the current value of i. The resulting value of factorial is then displayed, before going to the next iteration of the outer loop.

Although we have nested a for loop inside another for loop here, as we said at the outset, you can nest any kind of loop inside any other. We could have written the nested loop as:

  for (int i = 1; i <= limit; i++) {
    factorial = 1;       // Initialize factorial
    int factor = 2;
    while (factor <= i) {
      factorial *= factor++;
    }
    System.out.println(i + "!" + " is " + factorial);
  }

Now we have a while loop nested in a for loop. It works just as well, but it is rather more natural coded as two nested for loops because they are both controlled by a counter.

Important 

If you have been concentrating, you may well have noticed that you don't really need nested loops to display the factorial of successive integers. You can do it with a single loop that multiplies the current factorial value by the loop counter. However, this would be a very poor demonstration of a nested loop.

The continue Statement

There are situations where you may want to skip all or part of a loop iteration. Suppose we want to sum the values of the integers from 1 to some limit, except that we don't want to include integers that are multiples of three. We can do this using an if and a continue statement:

for(int i = 1; i <= limit; i++) {
  if(i % 3 == 0) {
    continue;                        // Skip the rest of this iteration
  }
  sum += i;                          // Add the current value of i to sum
}

The continue statement is executed in this example when i is an exact multiple of 3, causing the rest of the current loop iteration to be skipped. Program execution continues with the next iteration if there is one, and if not, with the statement following the end of the loop block. The continue statement can appear anywhere within a block of loop statements. You may even have more than one continue in a loop.

The Labeled continue Statement

Where you have nested loops, there is a special form of the continue statement that enables you to stop executing the inner loop – not just the current iteration of the inner loop – and continue at the beginning of the next iteration of the outer loop that immediately encloses the current loop. This is called the labeled continue statement.

To use the labeled continue statement, you need to identify the loop statement for the enclosing outer loop with a statement label. A statement label is simply an identifier that is used to reference a particular statement. When you need to reference a particular statement, you write the statement label at the beginning of the statement in question, and separated from the statement by a colon. Let's look at an example:

Try It Out – Labeled continue

We could add a labeled continue statement to omit the calculation of factorials of odd numbers greater than 10. This is not the best way to do this, but it does demonstrate how the labeled continue statement works:

public class Factorial {
  public static void main(String[] args) {
    long limit = 20;      // to calculate factorial of integers up to this value
    long factorial = 1;   // factorial will be calculated in this variable

    // Loop from 1 to the value of limit
    OuterLoop:
    for(int i = 1; i <= limit; i++) {
      factorial = 1;                   // Initialize factorial
      for(int j = 2; j <= i; j++) {
        if(i > 10 && i % 2 == 1) {
          continue OuterLoop;          // Transfer to the outer loop
        }
        factorial *= j;
      }
      System.out.println(i + "!" + " is " + factorial);
    }
  }
}

If you run this it will produce the output:

1! is 1
2! is 2
3! is 6
4! is 24
5! is 120
6! is 720
7! is 5040
8! is 40320
9! is 362880
10! is 3628800
12! is 479001600
14! is 87178291200
16! is 20922789888000
18! is 6402373705728000
20! is 2432902008176640000

How It Works

The outer loop has the label OuterLoop. In the inner loop, when the condition in the if statement is true, the labeled continue is executed causing an immediate transfer to the beginning of the next iteration of the outer loop.

In general, you can use the labeled continue to exit from an inner loop to any enclosing outer loop, not just the one immediately enclosing the loop containing the labeled continue statement.

Using the break Statement in a Loop

We have seen how to use the break statement in a switch block. Its effect is to exit the switch block and continue execution with the first statement after the switch. You can also use the break statement to break out from a loop when you need. When break is executed within a loop, the loop ends immediately and execution continues with the first statement following the loop. To demonstrate this we will write a program to find prime numbers. In case you have forgotten, a prime number is an integer that is not exactly divisible by any number less than itself, other than 1 of course.

Try It Out – Calculating Primes I

Start with the main()method in the class Primes, and declare nValues and isPrime. Then start a for loop that will loop through all integers from 2 to nValues.

public class Primes {
  public static void main(String[] args) {
    int nValues = 50;                        // The maximum value to be checked
    boolean isPrime = true;                  // Is true if we find a prime

    // Check all values from 2 to nValues
    for(int i = 2; i <= nValues; i++) {

Then we try dividing i by all integers less than its value.

      isPrime=true;                         // Assume the current i is prime

      // Try dividing by all integers from 2 to i-1
      for(int j = 2; j < i; j++) {
        if(i % j == 0) {        // This is true if j divides exactly
          isPrime = false;    // If we got here, it was an exact division
          break;              // so exit the loop
        }
      }

The final section prints out any primes.

      // We can get here through the break, or through completing the loop
      if(isPrime)                  // So is it prime?
        System.out.println(i);    // Yes, so output the value
      }
    }
  }
}

You should get the output:

2
3
5
7
11
13
17
19
23
29
31
37
41
43
47

How It Works

There are much more efficient ways to calculate primes, but this does demonstrate the break statement in action. The basic idea of the program is to go through the integers from 2 to the value of nValues, and check each one to see if it has an integer divisor less than the number being checked. The outer loop is indexed by i stepping through the possible values that need to be checked. The inner loop is indexed by j, the value of j being a trial divisor. This determines whether any integer less than the value being tested for primality is an exact divisor.

The checking is done in the if statement in the inner loop. If j divides i exactly i%j will be 0, so isPrime will be set to false. In this case the break will be executed to exit the inner loop – there is no point in continuing as we now know that the value being tested is not prime. The next statement to be executed will be the if statement after the closing brace of the inner loop block. You can also reach this point by a normal exit from the loop which occurs when the value is prime, so it is necessary to check the value of isPrime to see whether we do have a prime or not.

This example could be simplified if we used the labeled continue instead of the break statement:

Try It Out – Calculating Primes II

Try the following changes to the code in the Primes class.

public class Primes {
  public static void main(String[] args) {
    int nValues = 50;                     // The maximum value to be checked

    // Check all values from 2 to nValues
    OuterLoop:
    for(int i = 2; i <= nValues; i++) {
      // Try dividing by all integers from 2 to i-1
      for(int j = 2; j < i; j++) {
        if(i%j == 0) {                    // This is true if j divides exactly
          continue OuterLoop;             // so exit the loop
        }
      }
      // We only get here if we have a prime
      System.out.println(i);              // so output the value
    }
  }
}

How It Works

We no longer need the isPrime variable to indicate whether we have a prime or not, as we can only reach the output statement through a normal exit from the inner loop. When this occurs it means we have a prime. If we get an exact divisor, implying the current value of i is not prime, the labeled continue transfers immediately to the next iteration of the outer loop. The output from this version of the program is the same as before.

Breaking Indefinite Loops

You will find that sometimes you will need to use a loop where you don't know in advance how many iterations are required. This can arise when you are processing external data items that you might be reading in from the keyboard for example, and you do not know in advance how many there are. You can often use a while loop in these circumstances with the loop condition determining when the loop should end, but sometimes it can be convenient to use an indefinite loop instead, with a break statement to end the loop.

Try It Out – Calculating Primes III

Suppose we want our Primes program to generate a given number of primes, rather than check up to a given integer value. In this case we don't know how many numbers we need to check to generate the required number of primes. This is a case where an indefinite loop is useful. We can code this as follows:

public class FindPrimes {
  public static void main(String[] args) {
    int nPrimes = 50;                   // The maximum number of primes required

    OuterLoop:
    for(int i = 2; ; i++) {             // This loop runs forever

      // Try dividing by all integers from 2 to i-1
      for(int j = 2; j < i; j++) {
        if(i % j == 0) {                // This is true if j divides exactly
          continue OuterLoop;           // so exit the loop
        }
      }
      // We only get here if we have a prime
      System.out.println(i);            // so output the value
      if(--nPrimes == 0) {              // Decrement the prime count
        break;                          // It is zero so we have them all
      }
    }
  }
}

How It Works

This program is very similar to the previous version. The principal differences are that nPrimes contains the number of primes required, so the program will produce the first 50 primes, instead of finding the primes between 2 and 50. The outer loop, controlled by i, has the loop condition omitted, so the loop has no direct mechanism for ending it. The loop must be terminated by the code within the loop, otherwise it will continue to execute indefinitely.

Here the termination of the outer loop is controlled by the if statement following the output statement. As we find each prime, the value is displayed, after which the value of nPrimes is decremented in the if statement:

if(--nPrimes == 0) {      // Decrement the prime count
  break;                  // It is zero so we have them all
}

The break statement will be executed when nPrimes has been decremented to zero, and this will exit the outer loop.

The Labeled break Statement

Java also makes a labeled break statement available to you. This enables you to jump immediately to the statement following the end of any enclosing statement block or loop that is identified by the label in the labeled break statement. This mechanism is illustrated in the following diagram:

Click To expand

The labeled break enables you to break out to the statement following an enclosing block or loop that has a label regardless of how many levels there are. You might have several loops nested one within the other, and using the labeled break you could exit from the innermost loop (or indeed any of them) to the statement following the outermost loop. You just need to add a label to the beginning of the relevant block or loop that you want to break out of, and use that label in the break statement.

Just to see it working we can alter the previous example to use a labeled break statement:

public class FindPrimes {
  public static void main(String[] args) {
    int nPrimes = 50;                   // The maximum number of primes required

    // Check all values from 2 to nValues
    OuterLoop:
    for(int i = 2; ; i++) {                   // This loop runs forever

      // Try dividing by all integers from 2 to i-1
      for(int j = 2; j < i; j++) {
        if(i % j == 0) {                   // This is true if j divides exactly
          continue OuterLoop;             // so exit the loop
        }
      }
      // We only get here if we have a prime
      System.out.println(i);                  // so output the value
      if(--nPrimes == 0) {                     // Decrement the prime count
        break OuterLoop;                      // It is zero so we have them all
      }
    }
    // break OuterLoop goes to here
  }
}

The program works in exactly the same way as before. The labeled break ends the loop operation beginning with the label OuterLoop, and so effectively branches to the point indicated by the comment.

Of course, in this instance its effect is no different from that of an unlabeled break. However, in general this would work wherever the labeled break statement was within OuterLoop. For instance, it could be nested inside another inner loop, and its effect would be just the same – control would be transferred to the statement following the end of OuterLoop. The following code fragment illustrates this sort of situation. Our label this time is Outside:

Outside:
for(int i = 0 ; i< count1 ; i++) {
  ...
  for(int j = 0 ; j< count2 ; j++) {
    ...
    for(int k = 0 ; k< count3 ; k++) {
      ...
      break Outside;
      ...
    }
  }
}
// The labeled break transfers to here...

The labeled break is not needed very often, but when you need to break out of a deeply nested set of loops it can be invaluable since it makes it a simple operation.

Previous Next
JavaScript Editor Java Tutorials Free JavaScript Editor