Sunday, 5 October 2014

Different ways of iterating Map and their performance

There are 4 ways using which we can iterate through a map. These 4 ways are based on entrySet() and keySet().
Any collection can be iterated using for each loop and iterator. For map also, iteration is done using these two techniques.

Method 1: keySet() with for each loop.
Method 2: keySet() with iterator().
Method 3: entrySet() with for each loop.
Method 4: entrySet() with iterator().

Let us see each method one by one and their cost of performance :

Create a map for 100000 objects.

Map<Integer,String> map = new HashMap<Integer,String>();
for(int i = 0; i<100000;i++)
{
     map.put(i,"object"+i);
}

Now we have created a map for 100000 objects, let iterate this map using each method one by one.

Method 1 : keySet() with for each loop

   long start = System.currentTimeMillis();
Set<Integer> keySet = map.keySet();
for(Integer key : keySet)
  {
String value = map.get(key);
}
long end = System.currentTimeMillis();
System.out.println("Method 1 takes "+(end-start)+" milliseconds");


Method 2: keySet() with iterator()

long start = System.currentTimeMillis();
Set<Integer> keySet = map.keySet();
Iterator<Integer> iterator = keySet.iterator();
while(iterator.hasNext())
{
Integer key = iterator.next();
String value = map.get(key);
}
long end = System.currentTimeMillis();

System.out.println("Method 2 takes "+(end-start)+" milliseconds");


Method 3: entrySet() with for each loop

long start = System.currentTimeMillis();
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
for(Map.Entry entry : entrySet)
{
Integer key = entry.getKey();
String value = entry.getValue();
}
long end = System.currentTimeMillis();

System.out.println("Method 3 takes "+(end-start)+" milliseconds");


Method 4: entrySet() with iterator()

long start = System.currentTimeMillis();
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
Iterator<Map.Entry<Integer, String>> iterator = entrySet.iterator();
while(iterator.hasNext())
{
Map.Entry entry = iterator.next();
Integer key = entry.getKey();
String value = entry.getValue();
}
long end = System.currentTimeMillis();

System.out.println("Method 4 takes "+(end-start)+" milliseconds");

Output:-
Method 1 takes 109 milliseconds
Method 2 takes 168 milliseconds
Method 3 takes 63 milliseconds
Method 4 takes 68 milliseconds

From this observation, it is clear that entrySet() is faster than keySet(). So Method 1 and Method 2 are ruled out from the race.

Now to decide which to be used between Method 3 and method 4, we need to see our requirements.
If we want to modify the content of map during its iteration, then go for iterator(), because any attempt made to modify the content of map during its iteration using for each loop, will result in java.util.ConcurrentModificationException.

Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
for(Map.Entry entry : entrySet)
{
map.remove(entry.getKey());  // throws run time exception here.
String value = entry.getValue();
}
long end = System.currentTimeMillis();



Using iterator(), one can modify the content of map during its iteration.

Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
Iterator<Map.Entry<Integer, String>> iterator = entrySet.iterator();
while(iterator.hasNext())
{
Map.Entry entry = iterator.next();
iterator.remove();    //valid here
}

No comments:

Post a Comment