Beware of enhanced for loops!

With Java 5, enhanced for loop was introduced by which instead of writing a for loop like :
for(int i=0; i<list.size(); i++){
String str = list.get(i);
System.out.println(str);
}

you can simply write as :
for(String str: list){
System.out.println(str);
}

It saves few extra lines of code and of course very easy to use. But, a thing one might tend to forget which can lead to exceptions at run time is that when you are using the enhanced for loop, it internally uses an iterator for traversing through the list.
Which means, the internal Iterator might throw ConcurrentModificationException when you try to remove any object in the list by some other means at some other point in your code.

Excerpt from Javadoc about ConcurrentModificationException class:
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.

For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.

So, a code like the following code will always throw ConcurrentModificationException at runtime when it tries to remove the object from the list.
for(Object obj : list){
if(obj.equals(anotherObj)){
list.remove(obj);
}
}

Because, for traversing java internally uses the iterator. Whereas for removing, the code uses the method defined in the list and not the iterator. Hence the exception.

This also means that when you want to remove anything from your list or array or whatever, then you should not use the enhanced for loop at all!

Advertisements

11 comments

  1. Balaji Krishnan · · Reply

    interesting 🙂 i havent been following updates to the java lang pretty closely – so java’s syntax is a learning that i take away here, good to know.

    incidentally, C# has something similar called foreach and heres the syntax.
    foreach (var item in someList) Console.WriteLine(item); //crisper syntax eh?

    but it will lead to the same exception too. imo, mutating a list over iterating over it sounds evil and might be better to even avoid it. for your example – id do something like

    index = list.Contains(“teststring”);
    list.remove(index);

    contains() would just iterate over the list and return the index of the element. i dunno if java has one such built in, but the .net framework has one.

    1. I am not familiar with C#.. But looks more or less same..

      foreach (var item in someList) Console.WriteLine(item); //crisper syntax eh?
      Yea.. Java is also pretty much the same..

      index = list.Contains(“teststring”);
      list.remove(index);

      Yes. Java also has indexOf() method in place of Contains() and I can do this in Java.
      However, what I wanted was – not to just remove one element from the list but to remove many elements based on a dynamic condition.

      Say, for example I set few elements of the list as null in some method. And now I want to remove all those elements which were set to null. I can’t do it a single statement as shown above. I have to rely on some kind of loop and iterate till the end of the list to make sure all nulls are removed.

      My point here is, in such a case, I can’t use the enhanced for loop for doing it. Of course, it is kinda weird example to remove an object from a list while iterating it – this will vary the size of the list itself. But the enhanced for loop in java actually wouldn’t allow any kind of change for that matter. And, using the conventional for loop, I can even delete elements while iterating the list:

      for(int i=0; i<list.size(); i++){
      String elem = list.get(i);
      list.remove(elem);
      i–; //With this I make correction for the updated list size
      }

      1. Balaji Krishnan · ·

        yup. you’re absolutely right about that. and yeah, i got a feeling that there was much more than just checking for a single element 🙂 but again, the general philosophy of not mutating while iterating over the same datastructure would be a better option, imo.

        and i meant crisper syntax considering the type inference. notice that i did not have to call out the type for each item on the list.
        java – for(String /* explicit typing */ str: list)
        sharp – for(var /* type is inferred */ str in list)
        not much of a difference – yes. absolutely. just that these little language features excite me 🙂

      2. I too agree on the general philosophy of not mutating while iterating over the same DS. I avoid it mostly.. But at some places I have to use it! 😉

        And about the crisper syntax:
        java – for(String /* explicit typing */ str: list)
        sharp – for(var /* type is inferred */ str in list)

        In C# do you need to typecast that var to a string or something later ? Or the type is inferred later in the following statements as well?
        Because, even in java I could have written the super class “Object” (which is like var i guess) instead of String over there.. But if I have to any string manipulation later in the following statements, I should type cast it to string before I do.. However, I can just print it without typecasting.. If I am right, you should type cast it to string data type later to do string manipulations..

        And yes, of course! these little lang. features are always quite interesting to know and these are the ones a programmer can always exploit to write better code.. So, I am quite interested in these as well! 😉

  2. Balaji Krishnan · · Reply

    oh no. no way. no casts! casts are costly operations and can throw up. this is a pure language feature –
    so if we consider a general statement in any language, to be of the following form
    variable = expression;
    the compiler evaluates the type of the expression (RHS) and assigns it to the variable on the LHS.

    matter of fact, if you are using VisualStudio to write C# code, u can hover over the word ‘var’ and see the type information (string in this case) at design time. even the IDE knows it 🙂

    i just found you on twitter. you can follow me if you’re interested to know the other side of the world – C# and the .net framework etc. 🙂 nice knowing you here.

    1. Balaji Krishnan · · Reply

      the C# equivalent of java’s object would be ‘object’ as well. basically every datatype derives from object and u can cast back and forth etc. var has got nothing to do with it, its a nifty lang features which does the type inference work for ya. i can then write clean code, say

      without type inference: List t = new List();

      with type inf:
      var t = new List();
      which is the same as the above statement even at compile time.

      and the other major use of type inference is when you actually do not know the type name – known as anonymous types in the C# world.

      var v = new { Amount = 108, Message = “Hello” };
      http://msdn.microsoft.com/en-us/library/bb397696.aspx

      1. Okay.. That’s quite interesting! Thanks for the short tutorial! 😉

        I think I should learn C#.. Sounds really cool!
        esp this: var v = new { Amount = 108, Message = “Hello” }; That’s really amazing!

    2. Woow! Not requiring to type cast at all… That’s cool.. Nice feature definitely!

      Sure! I am already following you now 😉 Thanks for your comments and views.. I am glad as well to know you as well.. ‘virtually’! 😉

      1. Balaji Krishnan · ·

        Haha. thats the beauty of language design. so much fun wrapped up into a short keyword which is 3 letters (var) long 🙂 thanks Arthy, for being a friend! Have a good one!

  3. Balaji Krishnan · · Reply

    “I think I should learn C#.. Sounds really cool!” – wonderful to hear 🙂 you should give it a try sometime 🙂

  4. Thanks arthyvijayaraghavan.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: