Control Flow

Goals

Concepts

Language

Lesson

The programs you've seen up till now have been one-shot applications that go straight through, from beginning to end, with no detours. But what if some of the programming commands are optional? What if you want to repeat a command 100 times without retyping it? You'll need to learn about conditional statements and loops, which govern the control flow of your program. The word “control flow” refers to the “flow of control”, or how control passes from one part of the program to the next.

Decisions

if(…) … else …

The most basic conditional statement is if() …, which says, if some condition is true, then do such-and-such.

if(x > 0)
{
  System.out.println("x is positive");
}

If the condition is not true, nothing happens, unless you include the optional else … part of the statement.

if(x > 0)
{
  System.out.println("x is positive");
}
else
{
  System.out.println("x is negative");
  System.out.println("or maybe it is zero");
}

Java does not have an elseif statement, but if you put another if(…) in the body of the else, it functions the same. This is the only place where leaving off the braces of an else statement is acceptable. Do you see how the second if(…) statement is part of the first else statement? How might you reformat this to show the relationship between the else and the second if(…)? The code is completely acceptable as shown, however.

if(x > 0)
{
  System.out.println("x is positive");
}
else if(x == 0)
{
  System.out.println("x is zero");
}
else //no need to check again; there is only one possibility left
{
  assert x < 0 : "Hmmm... x should have been negative here."
  System.out.println("x is negative");
}

switch(…) …

An if(…) statement now and then works well, but sometimes you have a lot of decisions to make about the same variable or expression.

//not the best approach; better to use the switch() statement

//tells the months in season of the year in the Northern Hemisphere
final String[] months;
if(season.equals("spring"))
{
  months = new Array[]{"March", "April", "May"};
}
else if(season.equals("summer"))
{
  months = new Array[]{"June", "July", "August"};
}
else if(season.equals("fall") || season.equals("autumn")) //note variations accepted
{
  months = new Array[]{"September", "October", "November"};
}
else if(season.equals("winter"))
{
  months = new Array[]{"December", "January", "February"};
}
else
{
  assert false : season;
}

This can quickly get messy—and inefficient. Java has to make decision after decision, evaluating the same expression over and over. A better approach is to use the switch(…) statement, allowing Java to check the expression once and then, using an internal lookup table, quickly go to the correct decision branch in the code. The switch(…) statement always worked with numeric types, and in later versions of Java it works with type String as well. But note that the switch(…) statement only works if you are comparing number or strings for equality. For any other types of expressions, you have to go back to the trusty if(…) statement.

//switch() is a better approach to multiple equality decisions on the same expression

//tells the months in season of the year in the Northern Hemisphere
final String[] months;
switch(season)
{
  case "spring":
    months = new Array[]{"March", "April", "May"};
    break;
  case "summer":
    months = new Array[]{"June", "July", "August"};
    break;
  case "fall":  //note variations accepted
  case "autumn":
    months = new Array[]{"September", "October", "November"};
    break;
  case "winter":
    months = new Array[]{"December", "January", "February"};
    break;
  default:
    assert false : season;
}

Loops

If you need to perform some operation multiple times, you could type it in the source code multiple times (or copy and paste). Or you could use one of Java's loop statements. If you need the operation to perform just a little differently each time, use a variable and change it as needed in the loop.

Loops come with a check, either before or at the end, to make sure the loop does not go on forever (unless you want it to). This check functions similar to an if(…) statement. If you need more checks during the loop operation, just add an if(…) statement as needed; if you decide to exit the loop, use a break statement (see below).

do … while(…)

The do ... while(…) loop has a condition at the end. If the condition evaluates to true, the loop repeats at the top until it reaches the end, and then it checks the condition again. This continues until the condition evaluates to false.

The following example adds up the counting numbers until the sum reaches or exceeds the limit. Then it prints how many counting numbers it took to reach that sum.

Winning Number
final int limit = 50;
int sum = 0;
int number = 1;
do
{
  sum += number;  //add the current number to the sum
  number++;  //don't forget to go to the next number
}
while(sum < limit);
final int winningNumber = number - 1;
System.out.println("The counting number needed to attain the sum is " + winningNumber);

while(…) …

A while(…) … statement functions exactly like a do … while(…) statement, except that evaluation of the exit expression occurs before executing the loop body. In fact it might be better named the while(…) do … statement, except that this statement doesn't actually contain the keyword do.

The following algorithm is one way to add up all the numbers in an array of int values:

Array Sum Using while(…)
final int[] array = new int[]{40, 20, 10, 5};
long sum = 0;
int index = 0;
while(index < array.length)
{
  final int element = array[index]; //get the current array element
  sum = sum + element;  //add the current array element to the sum
  index++;  //go to the next array index
}
System.out.println("The sum of the array is " + sum);

When you become more comfortable with Java, you will probably prefer to combine some of the statements in the body to make the loop more compact:

Compact Array Sum Using while(…)
final int[] array = new int[]{40, 20, 10, 5};
long sum = 0;
int index = 0;
while(index < array.length)
{
  sum += array[index];  //add the current array element to the sum
  index++;  //go to the next array index
}
System.out.println("The sum of the array is " + sum);

We can use a while(…) … loop to improve the Winning Number solution above. We can add the current number to the sum and check it before even incrementing the number. This way the number will never advance if we have reached the limit, obviating the need to subtract one from the solution.

Better Winning Number
final int limit = 50;
int sum = 0;
int number = 1;
//add the current number to the sum and check it
while((sum += number) < limit)
{
  number++;  //go to the next number
}
System.out.println("The counting number needed to attain the sum is " + number);

for(…; …; …) …

The for(…; …; …) … statement, commonly referred to as a “for loop”, could be considered a form of “syntactic sugar”: it doesn't add any functionality you couldn't do with a while(…) statement, it just makes setting up the loop much easier. Look again at the Compact Array Sum Using while(…) code snippet above; you'll note that it has three basic sections:

  1. Variable initialization: int index =0
  2. Loop expression: index < array.length
  3. Expression variable update: index++

A for loop is essentially a statement that allows you to combine these three components in a compact way. Here is the Compact Array Sum Using while(…) program again, using a for loop instead of a while(…) statement. Even though the three components of the for loop are presented together on the same line, Java will invoke the components at the correct time, in the same order as in a while(…) statement. That is, the variable initialization occurs once before the loop begins; the loop expression is evaluated at the beginning of the loop each time, and the expression variable is updated at the end of the loop each time (but only if the expression evaluated to true—that is, only if the loop wasn't exited).

Array Sum Using for(…) Loop
final int[] array = new int[]{40, 20, 10, 5};
long sum = 0;
int index;
for(index = 0; index < array.length; index++)
{
  sum += array[index];  //add the current array element to the sum
}
System.out.println("The sum of the array is " + sum);

for( : ) …

Recent versions of Java have added an “enhanced for loop” that takes the form for( : ) …. The enhanced for loop does not contain three sections to allow for a loop counter. Instead the developer does not need to worry about a loop counter at all, and instead provides the variable that will iterate through the values, and the array containing the values over which to iterate. Compare the following to the Array Sum Using while(…) snippet above.

Array Sum Using Enhanced for(…) Loop
final int[] array = new int[]{40, 20, 10, 5};
long sum = 0;
for(int element : array)
{
  sum += element;
};
System.out.println("The sum of the array is " + sum);

By dispensing with a loop counter in your program, the enhanced for loop greatly reduces the risk of errors. A developer has to ensure that a loop counter is initialized correctly, that it is checked correctly at the correct location in the loop, and that it is incremented correctly at the right place. The last point is especially noteworthy, as almost every programmer will probably forget to increment a loop variable at least once at some point in his or her career. What would happen if you were to forget to increment a loop variable in a traditional loop?

Just as important, the enhanced for loop brings meaning to the variables in the loop. Rather than simply being an almost faceless placeholder, the variable in an enhanced for loop represents the thing that is being iterated in the array. You accordingly can and should provide a meaningful name to the iterating variable in the enhanced for loop.

break

The break statement, which you used already with switch(…), will exit a loop block just as it does with a switch(…) block. The following example shows how we might exit a loop if the sum were to be larger than some maximum threshold.

Array Sum with break
final int[] array = new int[]{40, 20, 10, 5};
final long max = 50;
long sum = 0;
for(int element : array)
{
  //make sure we don't go over the max
  if(sum + element > max)
  {
    break;  //skip everything else and exit the loop
  }
  sum += element;
};
System.out.println("The sum (kept under max) of the array is " + sum);

continue

The continue statement will also skip the rest of the loop, but instead of exiting the loop like break, continue will continue back at the top of the loop for the next cycle. Here is how we could use continue to skip over even numbers.

Array Sum of Odd Numbers Using continue
final int[] array = new int[]{44, 22, 11, 55};
long sum = 0;
for(int element : array)
{
  if(element % 2 == 0)  //if this number is even
  {
    continue;  //skip the rest of the loop and go to the next element
  }
  sum += element;
};
System.out.println("The sum of the odd numbers in the array is " + sum);

Review

Gotchas

In the Real World

Think About It

Self Evaluation

Task

Create a program named “Booker” to print a list of the best-selling single-volume books with more than 100 million copies sold according to Wikipedia on 2015-08-26.

Send your entire project to your teacher as a single, compressed archive.

See Also

References