Thursday, June 19, 2014

How HashMap Works in Java?

HashMap in Java
HashMap store Key/Value pairs just like HashTable. It is faster than HashTable and accept null values and it is not synchronized. These are the basic fundementals we know about HashMap. However, let us try to go through how Hashmap works in Java.

HashMap works on principle of hashing, we have put(key, value) and get(key) method for storing and retrieving Objects from HashMap. When we pass Key and Value object to put() method on Java HashMap, HashMap implementation calls hashCode() method on Key object and applies returned hashcode into its own hashing function to find a bucket location for storing Entry object, important point to mention is that HashMap in Java stores both key and value object as Map.Entry in bucket. Then, there is another important concept of Collision detection and Collision resolution in Java HashMap i.e What will happen when two objects have same hashcode?
According to the equals() and hashCode() contract, we know that for two objects to be equal, they need to have same hashcode. However, the oppositeis not true. i.e Two objects with same hashcode need not necessarily be equal. Here, when 2 objects with same hashcode is returned, this condition is called collision detection.

To resolve this collision, we should know that HashMap uses LinkedList to store object i.e the Map.Entry Object which comprises of Key and Value will be stored in a LinkedList. When an object is tried to be retrieved by calling the get(Object key) method, the linked list is traversed and if 2 objects are returned which has same hashCode, then it calls the key.equals() method to find the correct node in the linked list and return its associated value. So, it is very important that we maintain unique/unmodifiable keys.
Therefore, it is nice to remember and follow that using immutable, final object with proper equals() and hashcode() implementation would act as perfect Java HashMap keys and improve performance of Java HashMap by reducing collision. Immutability also allows caching there hashcode of different keys which makes overall retrieval process very fast and suggest that String and various wrapper classes e.g. Integer very good keys in Java HashMap.

Fail-Fast And Fail-Safe Iterators/ConcurrentModificationException

Fail-Fast And Fail-Safe Iterators/ConcurrentModificationException
Quite few times, while iterating over a List or collection and trying to perform some operations, we get ConcurrentModificationException. The idea behind getting to know the true reason for this is to know the type of iterator or to be precise, the type of collection that we are iterating on.
There are 2 types of Iterators:
1. Fail-Fast
2. Fail-Safe

The Fail-Fast iterators are ones which fails (And throws ConcurrentModificationException) when the collection's structure (i.e its size) changes upon iteration i.e whenever we add or remove an item from a collection or whenever a different thread adds/removes an item from a collection which is being interating currently, the ConcurrentModificationException is thrown. Collection Classes in java.util uses Fail-Fast iterators
Fail-Safe iterators are designed to overcome this. The classes in the package java.util.concurrent uses Fail-Safe iterators. i.e they do not throw ConcurrentModificationException when the collection structure i.e size changes while it is being in the middle of iteration
Looking at the example below, we see that Iterators on ArrayList from java. util package throws ConcurrentModificationException when during the iteration, we try to add another item to the ArrayList and hence change the structure of the collection. However, CopyOnWriteArrayList class in java.util.concurrent package uses Fail-Safe interators and hence, they do not throw the exception and are thread safe.
package com.sample.collectionsexamples;

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

public class FailFastAndFailSafeIteratorDemo {
 
   public static void main(String[] args) {
     List arrayList = new ArrayList();
     List copyOnWriteArrayList = new CopyOnWriteArrayList<>();
 arrayList.add(10);
 arrayList.add(20);
 arrayList.add(30);
 arrayList.add(40);
  
 copyOnWriteArrayList.add(10);
 copyOnWriteArrayList.add(20);
 copyOnWriteArrayList.add(30);
 copyOnWriteArrayList.add(40);
  
 iterateOperation("CopyOnWriteArrayList",copyOnWriteArrayList);
 iterateOperation("ArrayList", arrayList);
  
 }
 
 static void iterateOperation(String type, List numbers) {
   System.out.println("Iterating and adding item on: "+type);
       Iterator itr = numbers.iterator();
   while(itr.hasNext()) {
  // Add another integer 50 after 40
  // This code to add will fail for ArrayList 
                // throwing ConcurrentModificationException
  // But it works fine for CopyOnWriteArrayList
      if(itr.next() == 40) {
     numbers.add(50);
   }
 }
 System.out.println("Items in the list "+type+" = "+numbers);
} 

}