Saturday, 4 May 2013

Why and when can we encounter ConcurrentModificationException in Java.

Background

If you are a  beginner level Java developer and experimenting with Collections you may encounter this exception. Even I was taken with surprise when i first encountered such Exception.Let see why and when do we get such an Exception.
    Before we proceed take a look at the Iterator Example code in the post on Understanding Iterators. We will refer to a lot of things from that post.

Now if you recall the Iterator interface it was like -

public interface Iterator<E>

{
    boolean hasNext();
    E next();
    void remove();
}


Iterator object has a remove function but generally beginners tend to forget that. See the following code when you will encounter  ConcurrentModificationException.


Example Code

package testCodes;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorDemo {

    public static void main(String[] args) {

        List<String> nameList = new ArrayList<String>();
        nameList.add("John");
        nameList.add("Sam");
        nameList.add("kenny");

        nameList.add("Jessica");

        Iterator<String> namesIterator = nameList.iterator();
        System.out.println("Printing names");
        while (namesIterator.hasNext()) {
            String name = namesIterator.next();
            if (name.equals("Sam")) {
                nameList.remove(name);
            }
            System.out.println(name);
        }
    }
}

 Output


 Explanation

    Why did we get this Exception. Reason is simple. When we Iterate using an Iterator, Iterator objects expects there should be no modification in the  Collections which it points to. So how do we remove one might ask. For this reason we have .remove() method in Iterator interface. You can do something like below - 

while (namesIterator.hasNext()) {
            String name = namesIterator.next();
            if (name.equals("Sam")) {
                namesIterator.remove();
            }
            System.out.println(name);
     }


Code will correctly compile and run. It's a very simple point but programmers tend to forget it some time.

So basically you should not modify the collection when it is being iterated upon. Another simple example that would throw this exception is

        Map<String, Object> myMap = new HashMap<String, Object>();
        myMap.put("Aniket", 1);
        myMap.put("Abhijit", 2);
        for(String key: myMap.keySet()) {
            myMap.remove(key);
        }


Solution as I mentioned above is to use remove() method of the iterator.Another option could be use concurrent collections. See following example -

        Map<String, Object> myMap = new ConcurrentHashMap<String, Object>();
        myMap.put("Aniket", 1);
        myMap.put("Abhijit", 2);
        for(String key: myMap.keySet()) {
            myMap.remove(key);
        }


What internally happens is as soon as data is updated in a collection the corresponding iterator is updated too which generally does not happen in normal collections.


Related Links


Understanding Iterators in Java

Having some idea about Collections in Java lets see what is an Iterator and what is it used for? As described in post on Java Collection an Iterator object is used to iterate over elements stored in a Collection.

 You know that Collection is an Interface. Even List, Set, Queue are Interfaces which then have their own concrete implementations like ArrayList, HashSet, LinkedList etc. Collection Interface implements another Interface called Iterable.

If you go and open the sour code for Collection Interface in Java you will find -

public interface Collection<E> extends Iterable<E> 

{

 int size();

 boolean isEmpty();

 boolean contains(Object o);

 Iterator<E> iterator();

 Object[] toArray();

 <T> T[] toArray(T[] a);

 boolean add(E e);

 boolean remove(Object o);

 boolean containsAll(Collection<?> c);

 boolean addAll(Collection<? extends E> c);

 boolean removeAll(Collection<?> c);

 boolean retainAll(Collection<?> c);

 void clear();

 boolean equals(Object o);

 int hashCode(); 
} 

and if you go and see what there in Iterable Interface you will find -

public interface Iterable<T> 
{
    Iterator<T> iterator();
}


Iterator is again an interface whose source code is as follows -

public interface Iterator<E> 
{
    boolean hasNext();
    E next();
    void remove();
}


Note :  All these are just Interfaces(abstract functions). Their concrete implementation will be in the first concrete subclass.

Points to Note -
  • We can iterate only in one direction.
  • Iteration can be done only once. This means once we reach end of a series we must get a new iterator to iterate. 

Lets take an example to demonstrate how Iterator works -

package testCodes;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorDemo {

    public static void main(String[] args) {
       
        List<String> nameList = new ArrayList<String>();
        nameList.add("John");
        nameList.add("Sam");
        nameList.add("kenny");
        nameList.add("Jessica");
       
        Iterator<String> namesIterator = nameList.iterator();
        System.out.println("Printing names");
        while(namesIterator.hasNext())
        {
            System.out.println(namesIterator.next());
        }
    }

}




 Output

Understanding the code

    First we create a ArrayList called nameList and store some values in it. Note the use of Generics. nameList will and should always contain a String. If you try to add any other object Compiler will complaint. Also when you extract any element from the List you will always get a String object.

     Next we get an Iterator from the ArrayList. Note the Syntax. We can get such Iterator from any entity(interface/class) which come under Collection inheritance tree(Remember Collection implements Iterable). So we just need to use .iterator() function to get the respective iterator. Then we can iterate to get the elements. Note .hasNext() checks whether Collection(List/ArrayList in our case) has next element or not where as .next() will actually give you the next element.

Note :  Map and its sub classes/ sub interfaces are not a part of Collections.So you cannot use .iterator() function on it. There are other was to iterate over it's data but we shall cover that separately.

Understanding Generics in Java

When you talk about Collections, Generics are automatically introduced. After knowing basics of how Collections work let us explore the World of Generics.



Before we proceed to even understanding what generics is I want you remember one thing

                             "Generics is a Compile Time Concept"


By Generics you define what data type is associated with your Generic Class or a method. So at compile time when you do operations on your class or method compiler will always expect that generic type. Lets take an example to understand this better.
   Lets say you have a List to store name of some people. This is how you do it.

List nameList = new ArrayList();
nameList.add("John");   // 0th index
nameList.add("Sam") ;  // 1st index
etc

So far things look good. We created a List and we added some names to it. But now say I do something like below -
nameList.add(23);  // 2nd index

Notice here 23 is not a String but an integer. Even if some one has a name called 23 we must say "23". But the point to note here is that one can add anything to the List at this point of time. So far so good. Code will Compile and even run.

Lets see where the problem might occur.
String name1 = (String) nameList.get(0);
String name2 = (String) nameList.get(1);
String name3 = (String) nameList.get(2);  //Oops Error!

because 23 is a int and you can't type cast it into a String. Also note that even if you store and actual String every time we have to type cast it . Wondering if there is a better alternative ?

This is why we use Generics.

Let rewrite above example - 
List <String>nameList = new ArrayList<String>();
nameList.add("John");   // 0th index
nameList.add("Sam") ;  // 1st index

All good. Now lets add an integer -

nameList.add(23);  // 2nd index

At this point compiler will give error. Compiler know nameList can only have String and cannot accept integer . Program will not compile so running program will never come into picture. That's why we say generics is used for compile time safety.

Now lets extract valued from the List

String name1 = nameList.get(0);
String name2 = nameList.get(1);

That's right! No need to type cast. Compiler will know that nameList only contains String and hence it will always return a String.Lets revise benefits of using Generics -

Why Generics?

  • Stronger type checks at Compile time :

    A Java compiler applies strong type checking to generic code and issues errors if the code violates type safety. Fixing compile-time errors is easier than fixing runtime errors, which can be difficult to find.
  • Elimination of need to cast :

    The following code snippet without generics requires casting - 

    List list = new ArrayList();
    list.add("hello");
    String s = (String) list.get(0);
    
    
    When re-written to use generics, the code does not require casting - 

    List<String> list = new ArrayList<String>();
    list.add("hello");
    String s = list.get(0);   // no cast
    
    
  • Enabling programmers to implement generic algorithms :

    By using generics, programmers can implement generic algorithms that work on collections of different types, can be customized, and are type safe and easier to read.
 Note :  Generics is not supported by primitive Data types. So you cannot do something like List<int> myList  = new ArrayList<int>();. You will have to do List<Integer> myList  = new ArrayList<Integer>();


Creating Generic Classes

 So far we saw use of generics on existing classes that JDK provides like List. Now lets write generic class of our own.


 I am going to create my own generic data structure called MyDataStructure. Code is as follows - 

public class MyDataStructure<T> {
    
    T data;

    public T getData() {
        return data;
    }

    public void putData(T data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "MyDataStructure [data=" + data + "]";
    }
}

Notice that T. It's called type place holder - the type name T within angle brackets “<” and “>”. We use the same in all places in subsequent code. Now lets test this class.


public class TestGenerics {

    

    public static void main(String args[]) {

        MyDataStructure<String> myStringDataStructure = new MyDataStructure<String>();

        myStringDataStructure.putData("OpenSourceForGeeks");

        System.out.println(myStringDataStructure);

        MyDataStructure<Integer> myIntegerDataStructure = new MyDataStructure<Integer>();

        myIntegerDataStructure.putData(21);

        System.out.println(myIntegerDataStructure);

    }



}


and the output is : 
MyDataStructure [data=OpenSourceForGeeks]
MyDataStructure [data=21]

Diamond Syntax

MyDataStructure<String> myStringDataStructure = new MyDataStructure<String>();

Noticed how we have to provide same type parameters in both the declaration type
(MyDataStructure<String>) and the new object creation expression (new MyDataStructure<String>())

To simplify this diamond syntax is introduced in Java 7. In this type parameter in new Object creation expression can be omitted. Compiler infers the type from the declaration part.


So you can simply say
MyDataStructure<String> myStringDataStructure = new MyDataStructure<>();


Type Erasure

If you recollect I had mentioned in the beginning of this post that generics is compile time concept. This is also called type erasure. After compilation all generic code is replaced by concrete type. At Runtime there is no generics involved. 

Knowing this fact try to answer following question. What would be the output -

public static void main(String []args) {
    List<Integer> integerList = new LinkedList<Integer>();
    List<Double> doubleList = new LinkedList<Double>();
    System.out.println("integerList class: " + integerList.getClass());
    System.out.println("doubleList class:" + doubleList.getClass());
}

Output : 

integerList class: class java.util.LinkedList
doubleList class:class java.util.LinkedList

Reason : 

At runtime there are no generics. It's plain concrete classes that exist. To sum this up due to type erasure after compilation both types are treated as same LinkedList type.

Important points

  • It’s possible to define or declare generic methods in an interface or a class even if the class or
    the interface itself is not generic.
  • You cannot instantiate a generic type using new operator. Eg you cannot do -

    T data = new T(); or
    T[] data = new T[10];


    Also you cannot create arrays of generic classes.

    List<Integer>[] array = new List<Integer>[10]; // does not compile

    Of course you can do -

    List[] array = new List[10]; // compiles

    but not with generics

    For reference see ArrayList code. There we have

    public class ArrayList<E> extends.......
    and

    data structure in it is

    private transient Object[] elementData; // note no generics here

    Then add method is like

    public boolean add(E e) {
        ensureCapacity(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
  • Also note Generics does not support covariance or subtyping. Meaning you cannot do something like -

    List<Number> numbers = new ArrayList<Integer>(); // will not compile

Related Links 



Collections Example(ArrayList)

Before we dive further into Collections let me take an example to show how Collections actually work.Lets take an List example as it is the most simple to understand. You can then try similar operations on Set and Queue. Not the functions remain the same for all as all three implement Collection interface. Only their implementations will vary.

Code

package testCodes;

import java.util.ArrayList;
import java.util.List;

public class ListDemo {

    public static void main(String[] args) {

        List<String> nameList = new ArrayList<String>();
        nameList.add("John");
        nameList.add("Sam");
        System.out.println(nameList);
        nameList.add(0, "kenny");
        System.out.println("Size of list is " + nameList.size());
        System.out.println(nameList);
        nameList.remove("Sam");
        System.out.println(nameList);
        nameList.remove(0);
        System.out.println(nameList);
        System.out.println("Size of list is " + nameList.size());
    }
}

Output 


Explanation

   First we create a List name nameList and then populate it with some values.Not the use of polymorphism(Superclass reference i.e List to subclass object i.e ArrayList).  You can add values in any Collection using .add() method.Observer the .add(0, "kenny") method. You can specify index as the 1st argument. Since i have put 0 "Kenny" is added to the front of the list(index 0). .remove() is also similar. Either you can specify an object to be removed as an argument or index at which object is to be removed. You can print the size of collection using .size() method. There are various other methods in Collection that we will learn in time but for now these should suffice. You can now play around with other Collections like Set and Queue. 

.clear() is another simple method to try. It will simple remove all emenets from the Collection. After this if you do .size() you will get 0.

Tuesday, 30 April 2013

W: GPG error: http://ppa.launchpad.net precise Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 6AF0E1940624A220

It all started when i executed -
sudo apt-get update 
on my Ubuntu 12.04(Precise Pangolin). After fetching the required updates it showed me an error at the bottom - W: GPG error: http://ppa.launchpad.net precise Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 6AF0E1940624A220

Screen-shot for the same is given below -

Clearly we need to download the key from Ubuntu key server.

Things to check before you see Approach 1 and 2.
  1. Open the file ~/.gnupg/gpg.conf with the editor.
  2. From the terminal gedit ~/.gnupg/gpg.conf
  3. Go to 116th like
    keyserver hkp://keys.gnupg.net
  4. Comment this out and add line above it so the setup now looks like
    keyserver http://keyserver.ubuntu.com
    # keyserver hkp://keys.gnupg.net
    # keyserver mailto:pgp-public-keys@keys.nl.pgp.net
    # keyserver ldap://keyserver.pgp.com
  5. Save the file.

Trying Reset(Did not help. Same error persisted)

Enter the following command on the terminal - 
sudo rm /var/lib/apt/lists/* -vf
and then update your system using following command - 
sudo apt-get update && sudo apt-get upgrade

  • 1st Approach(Did not Work for me)

    Run the following command -
    sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 6AF0E1940624A220This did not solve my problem. I got connection timed out.
    Generally Ubuntu key-server uses port 11371 which may be blocked by tour firewall. So you can use 80 as the port -
    sudo gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 6AF0E1940624A220

    But even this did not solve my problem -
    Errors i got by following both methods in this approach are in below screen-shot.


    Note :  Here if you are getting Connection refused then this may be a proxy problem. Check if you are behind any proxy or firewall.

  • 2nd Approach(Worked for me)

       If the command are not doing it for you, you have to do it on your own. After a long research on this problem i finally decided that the best thing to do was manually download the key and add it.This is how i did it.






    Go to Ubuntu Key-server(Click here). Here you can search your key. In my case it was 6AF0E1940624A220. Note while searching for key pre-append the key with 0x. So search for 0x6AF0E1940624A220


    Click on the link provided in the pub section.

    Copy the whole text(highlighted in below screen shot) from the page and save it in a file(say filename is key1).



Once you have copied the data to file. Save it. Then run the following command
sudo apt-key add key1

You will get an "OK" response.

aniket@aniket-Compaq-610:~/Desktop$ sudo apt-key add key1
[sudo] password for aniket:
OK


And you are done. Repeat the procedure of other keys that might be missing.
Then you can run
sudo apt-get update
and you will not get any error. Update happens smoothly. Do let me know if you still have any doubts.

Related Links

t> UA-39527780-1 back to top