This was another discussion assignment at school, where I was asked to compare the different loops in Java. The original assignment was to just explain for and for-each loops, but I added the while, and do while in here as well. This isn’t a detailed explanation of how loops work in general, but rather a comparison between the different kinds.
Like many other programming languages, Java offers a few different options for loops. Loops are very useful parts of any programming language. The easiest advantage to explain to beginners is that they reduce the amount of code needed to do something more than once. Like print a list of names for example.
Most beginners quickly grasp how powerful loops can be, but will often struggle with the differences between all of the options. Hopefully I can give some insight on these differences to help increase your understanding of these loops.
The key differences between for, and for-each loops really has to do with pragmatics rather than semantics. What I mean, is that the different loops are more readable when used in their intended way. However it’s important to understand that all styles of loops in Java can be used to achieve the same thing as any other loop. There is one exception to this rule, but we’ll look at that later.
For loop
The main use of a for loop is to do something a predictable number of times. In other words, when we use a for loop, it’s typical that we know how many times we are going to iterate before executing the loop. An example would be if you were trying to draw an 8×8 grid. For simplicity we’ll just use ‘*’, since we haven’t worked with graphics libraries yet. This first example shows how you might draw the first row.
for (int i = 0; i < 8; i++) { System.out.print("*"); }
In the above example, we know that we want to print a very specific number of asterisks (*), and so we use a for loop. If you wanted to extend this program, you could make it so that the number of asterisks printed is controlled by user input.
Instead of saying “i < 8″, it could be “i < userInput”. This is an acceptable use of a for loop, because although we are using a variable to control the number of iterations, it’s still a predictable amount. Remember, that we can use any other style of loop to achieve the same thing, but a for loop is stylistically better because it looks the cleanest. It becomes easy to see this when we extend our code further and use a nested loop.
for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { System.out.print("*"); } System.out.println(); }
In the code above we print out 8 rows of 8 asterisks using a nested for loop. If we were using a graphics library to draw rectangles, the code would be even cleaner because we wouldn’t have the hanging “System.out.println();” in the outer loop. Like I said, you can achieve the same results using other kinds of loops, but it would not look as clean and easy to read.
Challenge: As a challenge, try and create the above example using a while loop. You should have a better understanding as to why a for loop is more ideal in this situation.
For-each loop
With the for-each loop, it is typical to use when you have a collection or array of objects that you would like to iterate through. As an example let’s say you are making a game that is similar to Space Invaders. You have an array of enemies falling towards the bottom of the screen, and you have to try and shoot them with your bullets. To destroy enemies you need to check for a collision between bullets and enemies. One way to do this is using a for-each loop to check the position of each enemy object in the array, against the position of each bullet.
For-each also provides an easy way to iterate through enums, (explained below) and here is a very simple example.
/* Note that the enum must be nested inside of a class, but not inside of a subroutine */
enum Days = {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
};
for (Days d : Days.values()) {
System.out.println(d);
}
The “:” reads out in English as “in”. So what we are saying in the for-each loop above is “for each element that we will call “d” in the list returned by Days.values(), do this…”. This program will output the days of the week.
Enums
I feel like I’m sort of shoe-horning enums into this post, but they play a very important roll in programs. The main roll of enums is to make code more readable by giving sensible names to the index of each element, rather than using numbers like 0, 1, .., and so on.
It is possible for example to have simply used an array to store the days of the week in my example above. The problem however, is that it’s difficult for a human to associate the relative index to each day of the week. There is no way to know that the number 1 represents Tuesday, with out looking at documentation or reading into unnecessary details of code.
When using groups of data that need to be used in a control statement such as a for, or for-each loop, enums can make code more readable when used in the right scenarios.
While Loop
The while loop is generally used when we don’t know exactly how many times we want to repeat a loop, but we know we want to loop until some condition becomes false. It’s a way of doing something until something else happens. Like updating the state of a video game while it is running.
As a practical example let’s say we want to get a number from a user, but we don’t want that number to be zero. We could write a while loop that continues to ask for input until the user provides a number that is non-zero.
/* To use the Scanner class, include "import java.util.Scanner;" outside of your class */ Scanner input = new Scanner(System.in); // set up our scanner for input int userInput = 0; // initialize to 0 so while loop starts as "true" // ask for input while input is equal to zero while (userInput == 0) { System.out.println("Please enter a non-zero number."); userInput = input.nextInt(); }
In practice, you would still have to fail-safe your program against other illegal inputs such as non-numeric inputs. If you run this code and try to type your name, for example, an exception will be thrown and the program will crash. But we’re only looking at the functionality of loops in this post, and not exception handling.
Again, it is possible to achieve this same functionality with other loops, but it just won’t look as pretty. It would take a little bit of extra code to get this to function the same with the for loop, and a lot of extra code to get this to work with a for-each loop. More code is generally more confusing and more error prone, which is bad.
Do While
The do .. while loop is another option that looks very tidy and clean when used in the right situation. That situation is when you don’t know for sure how many times you want to repeat something, but you know for sure it has to be done once.
An example would be rolling a die until it equaled some number like six. Say we want to count how many rolls it takes too. We know we want to roll the die at least once, and then continue rolling it until a six is rolled.
The nice thing about using a do .. while in this instance is that we don’t need to initialize the die before executing the loop, which makes the code easier to read in my opinion.
int count = 0; // counts the number of rolls int die; // no need to initialize thanks to our do .. while // roll the die until we get 6. do { die = (int)(Math.random() * 6) + 1; count++; } while (die != 6);
In this code, if the first roll of the die is a six, then the condition in the “while” will be false, and the code won’t be repeated. But, it will always run the statements in the do .. while at least once.
It’s probably become redundant to say this again, but you can also achieve the same results with the other loops as well. It just won’t look as clean if you do for the same reasons already mentioned.
Conclusion
All loops can be used in similar ways to achieve the same results, but they are designed to look clean and uncluttered in specific situations. Being uncluttered not only means being easier to read, but also reduces the amount of errors that could potentially occur. When deciding what type of loop to use in Java, it’s important to learn how each loop differs from one another and understand which one will look the cleanest in your situation.
Lastly, at the beginning of this post I mentioned there was one exception. That exception is that all loops can be infinite except for the for-each loop. An infinite while loop is as simple as while(true), and an infinite for loop looks like this: for(;;). As far as I’m aware of there is no way to make an infinite for-each loop. All other cases considered though, it’s still mostly about pragmatics and not semantics when choosing a loop for your program.
Like what you read? Please leave your comments below. If you have any suggestions or corrections to add to my post, feel free to share your insights. All feedback is appreciated.
Cheers,
Dan