From Java 5 onwards, we have a for-each loop for iterating over collection and array in Java. For each loop allows you to traverse over collection without keeping track of index like traditional for loop, or calling hasNext() method in while loop using Iterator or ListIterator. For-each loop indeed simplified iteration over any Collection or array in Java, but not every Java programmer is aware of some useful details of for-each loop, which we will see in this tutorial. Unlike other popular items from Java 5 release alias Generics, Autoboxing and variable arguments, Java developers tend to use for-each loop more often than any other feature, but when asked about how does advanced foreach loop works or what is basic requirement of using a Collection in for-each loop, not everyone can answer. This small tutorial and example aims to bridge that gap by going through some interesting foreach loop puzzles. So, without any further delay let's see our first puzzle on Java 5 for-each loop.
Advanced for loop Puzzle 1
Consider below code of Iterating over a user defined aggregator or collection class in Java, what does it will print or will it throw any exception or compile time error :
package test;
/**
* Java Class to show how for-each loop works in Java
*/
public class ForEachTest {
public static void main(String args[]){
CustomCollection<String> myCollection = new CustomCollection<String>();
myCollection.add("Java");
myCollection.add("Scala");
myCollection.add("Groovy");
//What does this code will do, print language, throw exception or compile time error
for(String language: myCollection){
System.out.println(language);
}
}
}
and here is our CustomCollection class, It's parametric generic class, similar to any other Collection class, backed by ArrayList and provides methods to add and remove items from Collection.
package test;
public class CustomCollection{
private ArrayListbucket;
public CustomCollection(){
bucket = new ArrayList();
}
public int size() {
return bucket.size();
}
public boolean isEmpty() {
return bucket.isEmpty();
}
public boolean contains(T o) {
return bucket.contains(o);
}
public boolean add(T e) {
return bucket.add(e);
}
public boolean remove(T o) {
return bucket.remove(o);
}
}
Answer :
Above code will fail to compile because our CustomCollection class doesn't implement java.lang.Iterable interface, as shown in below compile time error :
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - for-each not applicable to expression type
required: array or java.lang.Iterable
found: test.CustomCollection
at test.ForEachTest.main(ForEachTest.java:24)
Interesting fact to know is that for-each loop is applicable only to Java array and Collection classes which implements Iterable interface, and since all built-in Collection classes implements java.util.Collection interface, which already extends Iterable, this detail mostly gets unnoticed. You can see it in type declaration of Collection interface public interface Collection
Second For-Each Puzzle in Java
In following code example, which block of code will throw ConcurrentModificatoinException in Java. Here we are iterating over ArrayList using standard iterator and for-each loop and subsequently removing elements as well, you need to find out which code will throw ConcurrentModificationException and why? remember answer could be both, none or any one of them, so beware.
package test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* Java class to demonstrate inner working of for-each loop in Java
* @author Javin Paul
**/
public class ForEachTest2 {
public static void main(String args[]){
Collectionlist = new ArrayList ();
list.add("Android");
list.add("iPhone");
list.add("Windows Mobile");
// Which Code will throw ConcurrentModificationException, both,
// none or one of them
// example 1
Iteratoritr = list.iterator();
while(itr.hasNext()){
String lang = itr.next();
list.remove(lang);
}
// example 2
for(String language: list){
list.remove(language);
}
}
}
About 70% Java developers will say that first code block will throw ConcurrentModificatoinException, because we are not using Iterator's remove method for removing elements, instead we are using ArrayList's remove() method. But, not many Java developer will say same thing about for-each loop, because we are not using Iterator there. In reality, second code snippet will also throw ConcurrentModificationException, which is quite obvious after solving first puzzle. Since for-each loop internally uses Iterator to traverse over Collection, it also call's Iterator.next(), which checks for modification and throws ConcurrentModificationException. You can see this from following output, which you will get, when you run second code snippet after commenting the first one :
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at test.ForEachTest2.main(ForEachTest2.java:34)
That's all on this post about Java 5 for-each loop guys. We have seen, couple of common mistake Java programmers make, while writing traversing code for Collection class, especially removing element, while iterating over collection. Remember always use Iterator's remove method for deleting objects from any Collection e.g. Map, Set or List and keep in mind that for-each loop is just a syntactic sugar over standard Iterator code idiom.
Nice article. Understood the concept.
BalasHapusCheers,
http://www.flowerbrackets.com/java-treemap/