As we know, we can do iterations in Java with at least two ways: For-Loop, or While-Loop. We can actually do it by using recursive as well, but let’s take it aside for now. For this post, I just want to focus a bit about For-Loop.
In For-Loop itself, we can do the looping in at least three ways:
1. Common For-Loop.
This is the most common way of doing iteration in Java. This is the basic format:
List<Book> books = new ArrayList<Book>(); // Set<Book> books = new HashSet<Book>(); books.add(new Book(“One”, 1)); books.add(new Book(“Two”, 2)); books.add(new Book(“One”, 1)); for (int i=0; i<books.size(); i++) { Book book = books.get(i); // Do something with var book here. }
This iteration is good enough for you if your projects use Collection data type with List implementation or for Array. But it’s not good enough for any other Collection data types such as Vector or HashMap, since they don’t apply getter method for a specific index.
If, let’s say, one day your supervisor decides to change the data type from ArrayList to HashSet in order to prevent duplicates in the Books collection, the code above will no longer compile because HashSet doesn’t have ‘get’ method.
The code above is not flexible for modifications.
2. With Iterator.
Iterator will help to solve the flexibility issue found in the common For-Loop. This is how the code will look if you convert it to apply Iterator.
List<Book> books = new ArrayList<Book>(); // Set<Book> books = new HashSet<Book>(); books.add(new Book(“One”, 1)); books.add(new Book(“Two”, 2)); books.add(new Book(“One”, 1)); for (Iterator<Book> it = books.iterator; it.hasNext(); ) { Book book = it.next(); // Do something with var book here. }
The code above in this 2nd example is more flexible than the 1st one. It’s flexible because whether the books collection will use List data type or Set data type, the code will still compile and run just fine. It solves the flexibility issue found when you use the common For-loop.
Can it get even better than this? Yes, but no longer in terms of flexibility. It’s just in terms of readability.
3. Enhanced For-Loop.
Since JDK 5, Java has launched a new form of loop, which they call Enhanced For-Loop. Actually this loop will implicitly use Iterator implementation as shown in the previous example. Implicitly. With this new for-loop format, the code will look better.
This is how the code will look if you use the Enhanced For-Loop instead.
List<Book> books = new ArrayList<Book>(); // Set<Book> books = new HashSet<Book>(); books.add(new Book(“One”, 1)); books.add(new Book(“Two”, 2)); books.add(new Book(“One”, 1)); for (Book book: books) { // Do something with var book here. }
Now, don’t you think that this one looks much nicer than the previous one? It’s more readable, and at the very least it saves you one line of code for each iteration.
The constraint here is that the declared Collection variable must use Generics. Anyway, actually it’s not really fair to call it a constraint. It’s more correct to consider it a feature. Generic is a very good Java practice to save you from wasting your time of compiling, deploying, and running the program just to encounter ClassCastException.
Indeed there are cases where it is necessary to use the classic For-Loop (the 1st option) instead of the others. One example is when the loop index is going to be used somewhere in the iteration. It usually happens when the sequence of the data inside the collections need to be maintained, such as ArrayList, Vector, or plain Array. If the sequence doesn’t matter, it’s advised to follow this formula:
Enhanced For-loop > For-Loop with Iterator > Common For-Loop.