Espresso: A Concentrated Introduction to Java


Loops in Java

Summary: We consider Java's primary iterative mechanisms for repeating sections of code.

Prerequisites: Basics of Java. Conditionals. Booleans.

Contents:

Introduction: Control Structures for Repetition

As we considered in our discussion of conditionals, most interesting algorithms include more than a simple sequence of operations. Conditionals permit algorithms to make decisions and to execute different sequences that depend on input or other conditions. However, many algorithms need to do more than simply make decisions, they must also execute the same (or similar) steps repeatedly. We call code constructs that repeat steps loops.

There are certainly a wide variety of ways in which we repeat code. For example, we might apply a function (method) to each element in a list, update an estimate until it is close enough to a desired result, continue reading and processing information from a file until there is no more information to process, or even beat batter 40 times (as in a recipe).

Computer scientists have described two general mechanisms for repeating steps: recursion and iteration. Recursion is beyond the scope of this section and has been covered briefly in the reading on static methods. Suffice to say, recursion works by having a method call itself again and again until the process is computed. Iteration provides a more explicit mechanism for repetition, although one that is slightly harder to analyze for correctness.

Most imperative languages provide three kinds of iterative control structures. One iterative loop control structure supports a fixed number of repetitions (e.g., beat the mixture 40 times; for each element of this list, do ...). We traditionally call such structures for loops. Often, this control structure gives you an associated counter variable.

A second looping control structure allows you to repeat an action for as long as a condition holds (e.g., as long as the input has not all been read, read a line and process it; as long as the estimate is not close enough, refine the estimate). We tend to call such loops while loops. Unlike for loops, which typically call for a fixed number of repetitions, while loops typically have an unknown number of repetitions. (When you formally study algorithms, you will find that we will often want to predict an upper bound for the number of repetitions.)

A third looping control structure is a slight variant of the while loop. In a repeat loop, work continues until a condition holds. For example, you might keep working on an assignment until it is correct. Repeat loops are quite similar to while loops, except that while loops check the condition before they execute the body of the loop and repeat loops check the condition afterwards.

We will, of course, consider how Java supports all three iterative looping styles.

While Loops

We'll begin with while loops, because they are perhaps the most general. (They are no more general than repeat loops, but they are certainly more general than the fixed-repetition for loops.) In Java, the form of a while loop is as follows:

while (test) {
  body-statements;
} // while
next-statement;

In executing this loop, Java evaluates the test, which must be a boolean expression. If the test fails (returns false), the loop terminates and Java moves on to the next statement. Otherwise, Java executes the statements in the body of the loop and then goes back and tries the test again. Importantly, the test is only executed once per repetition, so even if the test stop holding in the middle of the series of statements, the series continues to execute.

For example, here's some simple code to read a series of grades and stop when the user enters the special grade of 0.

boolean done = false;
PrintWriter pen = new PrintWriter(System.out, true);
BufferedReader eyes = new BufferedReader(new InputStreamReader(System.in));
int nextGrade = 0;
int numGrades = 0;
int sumGrades = 0;
while (!done) {
  pen.print("Enter the next grade: ");
  nextGrade = Integer.parseInt(eyes.readLine());
  if (nextGrade != 0) {
    sumGrades = sumGrades + nextGrade;
    numGrades = numGrades + 1;
  } // if (nextGrade != 0)
  else {
    done = true;
  }
} // while (!done)

Note that the testing is only done when the body finishes. If the body makes the test temporarily false and then true again, the loop still continues. The done is often called the loop sentinel, a variable upon which repetition of the loop continues.

Do Loops

In Java, repeat loops are called do loops. Do loops are useful when you need the body of the loop executed once before the test. It is certainly possible to simulate do loops by copying and pasting the body before the code before the loop, most programmers find such a technique inelegant, at best.

Do loops have the form

do {
  body-statements;
} while (test);
next-statement;

Their meaning is easiest defined in terms of the corresponding while loop:

body-statements;
while (test) {
  body-statements;
} 
next-statement;

Note that I have not commented the end brace in the do loop. This is the only time you won't need to comment your ending brace.

We can use do loops to simplify the earlier code.

do {
  pen.print("Enter the next grade: ");
  nextGrade = Integer.parseInt(eyes.readLine());
  if (nextGrade != 0) {
    sumGrades = sumGrades + nextGrade;
    numGrades = numGrades + 1;
  } // if (nextGrade != 0)
} while (nextGrade != 0);

For loops

As suggested in the introduction, in many algorithms you want to execute a statement (or block of statements) a fixed number of times. For example, to calculate the factorial of N, we might multiply 1 by the numbers from one to N. We might express this computation in psueodcode as

result = 1
for each value, v, between 1 and N
  multiply result by v, updating result
return the final result

Many programming languages provide a structure known as the for loop especially for situations like this. Traditional for loops allow you to specify only a counter variable, a starting value, and a finishing value. Java provides a more general form of the for loop. It has the form

for (initialization; test; increment) {
  body-statements;
} // for

The test must be a boolean expression; the initialization and increment can be any kind of statement. However, the initialization is typically a variable declaration and assignment.

In effect, this kind of for loop is equivalent to

{
  initialization;
  while (test) {
    body-statements;
    increment;
  } // while (test)
}

That is, just as in the case of the do loop, Java's for loop is simply a clearer way to phrase a certain kind of operation.

Fortunately, many Java programmers write for loops primarily in the context of the less-general counting for loop, in which case the loops typically have the form

for (int counter = starting-value; counter <= ending-value; counter++) {
  body-statements;
} // for (counter)

The postfix ++ operation is shorthand for add 1.

For example, we can solve our initial factorial problem as follows

  /**
   * Compute n!.
   */
  public int factorial(int n) {
    int i;    // A counter variable
    int fact; // The factorial of n
    fact = 1;
    for (i = 1; i <= n; i++) {
      fact = fact * i;
    } // for
    return fact;
  } // factorial(int)

For-each Loops

Some languages provide an interesting variation of the for loop. Rather than repeating the loop body for each value in a certain range, these for-each loops repeat the loop body for each value in a collection of values. For example, we might want to write something like the following:

For each student, s, in this class
  print information about s

Like for loops, these loops execute their body for a fixed number of steps. Unlike for loops, for each loops determine their number of steps from the size of the collection, rather than the range of numeric values.

For each loops in Java have the form

for (Type element : collection) {
  body-statements;
} // for (element)

We will return to for-each loops when we study collections in Java.

History

Wednesday, 21 September 2005 (morning) [Samuel A. Rebelsky]

Saturday, 24 September 2005 [Samuel A. Rebelsky]

Thursday, 9 February 2006 [Samuel A. Rebelsky]


This page was generated by Siteweaver on Thu Mar 30 15:24:27 2006.
The source to the page was last modified on Thu Feb 9 13:42:02 2006.
This page may be found at http://www.cs.grinnell.edu/~rebelsky/Espresso/Readings/loops.html.

You may wish to validate this page's HTML ; Valid CSS! ; Check with Bobby

Samuel A. Rebelsky
rebelsky@grinnell.edu