Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java for each loop working

I was working on certain task, when incidentally did something wrong according to me but the code executed and provided correct result. I was little surprised and had question in mind how all these for each loop works. Example (sample program),

public static void main( String[] args )
{
    String myInput = "hello , hi , how are you ";
    String[] splitted = myInput.split(",");
    List<String> mylist = new ArrayList<String>();
    for (String output : splitted) 
    {
        mylist.add(output);
    }


    for (String output : mylist) 
    {
        System.out.println(output);
        mylist = new ArrayList<String>(); //It worked 
        mylist.add(output);
    }

    for (String output : splitted) 
    {
        mylist.add(output);
    }

    for (String output : mylist) 
    {
        System.out.println(output);             
        mylist.add(output); // After this line it threw exception java.util.ConcurrentModificationException
    }

}

I was curious to know and while searching I found one more post that said we can remove elements from list if we used iterator approach, So I tried,

for (String output : splitted) 
{
    mylist.add(output);
}
for (Iterator iterator2 = mylist.iterator(); iterator2.hasNext();)
{
    String string = (String) iterator2.next();
    System.out.println(string);
    iterator2.remove(); //It worked but if I used the same thing to remove element from original list it threw exception.
}

Now I just want to know what is happening behind the every for each loop quoted above.
I want to know the technical aspect, I know I can not modify the collection in for each loop but in some case stated above it worked why?

like image 776
dbw Avatar asked Nov 26 '25 02:11

dbw


1 Answers

Now I just want to know what is happening behind the every for each loop quoted above

 1. for (String output : splitted) 
    {
        mylist.add(output);
    }

This adds each output String from splitted array to the mylist list.

2. for (String output : mylist) 
{
      System.out.println(output);
      mylist = new ArrayList<String>(); //It worked 
      mylist.add(output);
}

The for statement is governed by the following production:

for ( FormalParameter : Expression )
            Statement

where Expression must be an instance of java.lang.Iterable, or an array. So this for:each loop is equivalent to this:

Iterator<String> iterator = mylist.iterator();
while (iterator.hasNext()) {
    System.out.println(output);
    mylist = new ArrayList<String>(); //It worked 
    mylist.add(output);
}

Here mylist.iterator() will return a new instance of Iterator type:

public Iterator<E> iterator() {
        return new Itr();
}

So even if you are creating new ArrayList instances and assigning them to mylist on each iteration, the iterator obtained from the original mylist will still have a reference to the original mylist and will keep iterating through the elements of original mylist. The iterator keeps a reference to the list it was created on. The assignment mylist = new ArrayList<String>() has no effect on the data that the iterator works on because it changes the variable mylist and not the list itself.

3. for (String output : mylist) 
    {
        System.out.println(output);             
        mylist.add(output); // After this line it threw exception java.util.ConcurrentModificationException
    }

Below statement explains this behavior. It is copied from Arraylist doc:

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

4. for (Iterator iterator2 = mylist.iterator(); iterator2.hasNext();)
{
    String string = (String) iterator2.next();
    System.out.println(string);
    iterator2.remove(); //It worked but if I used the same thing to remove element from original list it threw exception.
}

The above statement also explains the behavior of this for loop: the list can be structurally modified by the iterator's own remove or add methods while iterating through the list.

like image 124
Debojit Saikia Avatar answered Nov 28 '25 17:11

Debojit Saikia



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!