Friday, November 14, 2014

This Should Throw You For a Loop

Hopefully you digested the information from my last post about while loops and you're feeling eager for more.  Fortunately, the rest of what you need to know about loops should come easily if you're already comfortable.

There are two other basic loop structures available to Java developers.  These are the for loop and the do/while loop.  As with the while loop, you could conceivably accomplish any looping task with either of these, but usually one or another will jump out at you as being best suited to the task at hand.

Since we've already looked at while, let's look at do/while.  We'll start with making a simple loop that duplicates the function of the first one from the while loop post:

boolean keepRunning = true;

do {
    System.out.println("I am in a loop.");
    keepRunning = false;
} while ( keepRunning );

Note that it really is the same inside the loop, only the location of the 'while', along with an added semicolon, and the addition of the word 'do' make it any different.  So why do we even have it?  The reason is that a while loop is an entry condition loop, whereas do/while is an exit condition loop.  When you reach a while loop, if the condition for which it tests is false you will never execute it at all, whereas a do loop will always execute at least once.

The difference is better illustrated if we start with 'keepRunning' set to false.

boolean keepRunning = false;

System.out.println("About to enter loop.");
while ( keepRunning ) {
    System.out.println("I am in a loop.");
}
System.out.println("Done with loop.");

Will generate the following output:
About to enter loop.
Done with loop.

Whereas:

boolean keepRunning = false;

System.out.println("About to enter loop.");
do {
    System.out.println("I am in a loop.");
} while ( keepRunning );
System.out.println("Done with loop.");

Will generate this:
About to enter loop.
I am in a loop.
Done with loop.

As with a while loop, and ignoring the possibility of multiple threads, if you ever want it to exit something needs to happen to make the exit condition evaluate to false.

That about sums up the differences between while and do/while.  Use whichever one makes the most sense based on the code you need to execute and the variables you have available to you.  You'll get a feel for it over time.  Without having done any surveys or run any metrics, I'd say that the regular while loop is used several times more often than do/while.

The other loop structure you need to know about, and perhaps the most commonly used of all, is the for loop.  It works like this:

for( starting condition ; loop conditional ; loop increment ) {
   //do something
}

Lean back and take a deep breath, it's not that bad.  To prove it, let's duplicate the code for looping five times (for is most commonly used for counting or iterating over some multiple part data structure).

First, a refresher.  In my previous post I put this up as how to use a while loop to generate five lines of output:

int runCount = 0;

while ( runCount < 5 ) {
    System.out.println("I am in a loop.");
    runCount ++;
}
This loop is an absolutely perfect candidate to use a for loop.  Here's the same thing expressed as a for:

for (int runCount = 0 ; runCount < 5 ; runCount ++ ) {
    System.out.println("I am in a loop.");
}

This is cleaner, more concise, and just plain shorter than the same loop expressed as a while.  It also illustrates some syntax differences of which you need to be aware.

First of all, note that 'runCount' is available ONLY within the loop parentheses and in the body of the loop.  Once you reach the closing bracket it goes out of scope.  This differs from the while loop and is a potential 'gotcha':

This is perfectly valid:

int runCount = 0;

while ( runCount < 5 ) {
...
}

System.out.println("The value of runCount is now " + runCount ); 


But this is not:

for ( int runCount = 0 ; runCount < 5  ; runCount ++ ) {
...
}

System.out.println("The value of runCount is now " + runCount ); 

You will receive a compiler error because runCount is completely unknown by the time you reach that attempt to print it out.  You could of course write it like this to get around the problem:

int runCount;

for ( runCount = 0 ; runCount < 5  ; runCount ++ ) {
...
}

System.out.println("The value of runCount is now " + runCount ); 

Note that one can pretty much mechanically translate between while and for loops.  Just move the first and third terms inside the parentheses to before the while and just before the closing curly brace.

The for loop is a natural fit for processing arrays and Collections, both of which I will be discussing soon.  You can use the value of the index variable (runCount in this case) inside the loop for all sorts of reasons, providing a counter, spitting out line numbers, whatever you need.

By convention, when you create an index variable in a for loop, and have no particular name for it, we tend to just use the letter i.  You'll see this kind of thing a lot:

for ( int i = 0 ; i < 10 ; i++ ) {
  System.out.println("Loop iteration " + i );
}

Well, to be fair, you'll see something that starts that way but actually DOES stuff a lot.

It is also possible to embed one loop inside of another.  You can't use 'i' again, so we move on to 'j' (then 'k', 'l', etc. if we want to go nuts.  Try not to go nuts).

This is an extremely basic example of that:

for ( int i = 0 ; i < 5 ; i++ ) {
    for ( int j = 0 ; j < 5 ; j++ ) {
        int product = i * j ;
        System.out.println (i + " X " + j + " = " + product );
    }
}

These few lines of code will generate 25 lines of output:

0 X 0 = 0
0 X 1 = 0
0 X 2 = 0
0 X 3 = 0
0 X 4 = 0
1 X 0 = 0
1 X 1 = 1
1 X 2 = 2
1 X 3 = 3
1 X 4 = 4
2 X 0 = 0
2 X 1 = 2
2 X 2 = 4
2 X 3 = 6
2 X 4 = 8
3 X 0 = 0
3 X 1 = 3
3 X 2 = 6
3 X 3 = 9
3 X 4 = 12
4 X 0 = 0
4 X 1 = 4
4 X 2 = 8
4 X 3 = 12
4 X 4 = 16

The various loops are critical to your understanding of software development.  Get comfortable with them, then get more comfortable with them.

As always, if you have comments or questions, please post them.  I'd love to hear from you.

View code here