2 examples of Java for each circular usage puzzle (advanced usage method)

  • 2020-04-01 03:15:56
  • OfStack

In Java, the for-each loop simplifies the traversal of any Collection or array, but not every Java programmer knows the details of the for-each loop described in this article. With Java 5 release other terms: release alias generics, automatic encapsulation and variable parameter, Java developers use of for-each loop than any other features more frequently, but when asked about how advanced the for-each loop, or what is in the for-each loop using a Collection of basic needs, not everyone can answer.

This tutorial and examples are designed to fill in the gaps above by delving into a few interesting puzzles in the for-each loop. Okay, without further ado, let's take a look at our first problem in the Java5 for-each loop.


Advanced loop problem 1

Consider the following section of code that iterates through a user-defined aggregator or collection class, what it will print, whether it throws an exception or a compiler error:


package test;


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);
        }
    }
}

Below is our CustomCollection class, which is a generic class, like any other Collection class, that relies on the ArrayList and provides methods to add and remove items from the Collection.


package test;

public class CustomCollection<T>{
    private ArrayList<T> bucket;

    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);
    }   

}

The answer:

The above code will not be compiled because our CustomCollection class does not implement the java.lang.iterable interface. The compile time error is as follows:


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)

An interesting fact to learn from this is that: The for-each loop applies only to the Java array and Collection classes that implement the Iterable interface, and since all the built-in Collection classes implement the java.util. So to solve the above problem, you can simply have CustomCollection implement the Collection interface or subabstractcollection, which is the default generic implementation and shows how to use both abstract classes and interfaces for greater flexibility. Now let's look at the second puzzle of the for-each loop:


The second problem with the Java for-each loop:

In the following code example will throw ConcurrentModificationException. Here we use the standard iterator and for-each loop through the ArrayList, then remove elements, you need to find out which code will throw ConcurrentModificationException, why? Note that the answer may be both, neither or either.


package test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;


public class ForEachTest2 {  

    public static void main(String args[]){
        Collection<String> list = new ArrayList<String>();
        list.add("Android");
        list.add("iPhone");
        list.add("Windows Mobile");

        // Which Code will throw ConcurrentModificationException, both, 
       // none or one of them

        // example 1        
        Iterator<String> itr = list.iterator();
        while(itr.hasNext()){
            String lang = itr.next();
            list.remove(lang);
        }

         // example 2
        for(String language: list){
            list.remove(language);
        }
    }
}

About 70% of the Java developers will say that the first block of code will throw ConcurrentModificationException, because we did not use the iterator remove method to remove elements, but use the ArrayList remove () method. However, not many Java developers would say the same thing about the for-each loop, because we're not using iterator here. In fact, the second code snippet will throw ConcurrentModificationException, this after solved the first confused becomes obvious. Since the for-each loop for internal use the Iterator to walk through the Collection, it is also called the Iterator. Next (), it will check (element) change and throw ConcurrentModificationException. You can see this from the following output, after commenting out the first code snippet, when you run the second code snippet you get the following output.


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 about the Java5 for-each loop. We've seen a lot of problems with Java programmers writing code that traverses a Collection class, especially when deleting elements while traversing the Collection. Keep in mind that you always use the remove method of Iterator when removing objects from any Collection (such as Map, Set, or List), and that the for-each loop is just syntactic sugar on top of the standard usage of the standard Iterator code.

Syntactic sugar, also translated as sugar-coated grammar, is a term coined by British computer scientist Peter John landa-peter j. Landin to refer to a syntax added to a computer language that does not affect the functionality of the language but is easier for programmers to use. Generally speaking, the use of syntax sugar can increase the readability of the program, thus reducing the chance of errors in the program code.


Related articles: