Showing posts with label Collections. Show all posts
Showing posts with label Collections. Show all posts

How to convert HashMap to Synchronized Map ?

In this tutorial we will see about how to convert HashMap to synchronized Map. As we know already that HashMap is not synchronized by default.

Synchronize is nothing but making the HashMap to thread safe and by multi-threading environment only one user can remove or edit the Map values. For example if we are using HashMap only for read operation then making synchronized Map is not necessary. Only when multi users or more threads tries to update or remove same key or value from HashMap then we need to make HashMap synchronized for thread safe purpose.

In Java we can do this very easily by using java.util.Collections class as like give below.



Map<String, Object> myMap = new HashMap<String, Object>();
.
.
.  
.
myMap = Collections.synchronizedMap(myMap);


From above code snippet we have declared myMap as HashMap and later in below code we have converted same HashMap instance to synchronized Map. Since this is a simple interview question which asked in 2 to 3 yrs experience level. Hope you are clear now how to convert HashMap to synchronized Map.

Above we have seen how to convert HashMap to SynchronizedMap. Even by converting SynchronizedMap its not guarantee that values will be thread safe we are editing or removing on same Object using multiple Thread. As per  Collections#synchronizedMap() in Oracle docs we need to make operations on Map with synchronized block as mentioned in Oracle docs.  

Lets see all scenarios with details example of 

  1. Accessing updated HashMap without converting to SynchronizedMap under Multi Threading.
  2. Accessing updated HashMap just converting to SynchronizedMap under Multi Threading.
  3. Accessing updated HashMap with converted to SynchronizedMap & Synchronized block under Multi Threading.

Example - 1 : Accessing updated HashMap without converting to SynchronizedMap under Multi Threading.


public class HashMapTest implements Runnable{
 
 // Initializing new HashMap
 private Map<String, String> myMap = new HashMap<String, String>();
 
 public void run() {
  String threadName = Thread.currentThread().getName();
  String oldValue = myMap.get("myKey");
  String newValue = oldValue+threadName;
  myMap.put("myKey", newValue);
  System.out.println(threadName+" : "+myMap.get("myKey"));
 }
 
 public static void main(String[] args) {
  HashMapTest obj = new HashMapTest();
  
  // Adding values into HashMap
  obj.addValues();
  
  // Creating multiple Thread and starting
  for(int i=0;i<5;i++){
   new Thread(obj).start();
  }
  
 }
 public void addValues(){
  myMap.put("myKey", "Java Discover - ");
 }
}


OUTPUT:


Thread-0 : Java Discover - Thread-3
Thread-1 : Java Discover - Thread-3
Thread-2 : Java Discover - Thread-3
Thread-3 : Java Discover - Thread-3
Thread-4 : Java Discover - Thread-3




In above example we have placed 1 value in HashMap and in run() method we trying to upend Thread name to existing value. Each thread names need to be upended in the value, where as we can see only Thread-3 has upended with original value. Remaining 4 Thread names are not updated correctly. Next example lets see just by converting HashMap to SynchronizedMap.



Example - 2 : Accessing updated HashMap just converting to SynchronizedMap under Multi Threading.


public class HashMapTest implements Runnable{
 
 // Initializing new HashMap
 private Map<String, String> myMap = new HashMap<String, String>();
 
 public void run() {
  String threadName = Thread.currentThread().getName();
  String oldValue = myMap.get("myKey");
  String newValue = oldValue+threadName;
  myMap.put("myKey", newValue);
  System.out.println(threadName+" : "+myMap.get("myKey"));
 }
 
 public static void main(String[] args) {
  HashMapTest obj = new HashMapTest();
  
  // Adding values into HashMap
  obj.addValues();
  
  // Converting HashMap to Synchronized Map 
  obj.convertMapToSynMap();
  
  // Creating multiple Thread and starting
  for(int i=0;i<5;i++){
   new Thread(obj).start();
  }
  
 }
 public void convertMapToSynMap(){
  myMap = Collections.synchronizedMap(myMap);
 }
 public void addValues(){
  myMap.put("myKey", "Java Discover - ");
 }
}


OUTPUT:


Thread-0 : Java Discover - Thread-1
Thread-1 : Java Discover - Thread-1
Thread-2 : Java Discover - Thread-1Thread-2
Thread-3 : Java Discover - Thread-1Thread-2Thread-3
Thread-4 : Java Discover - Thread-1Thread-2Thread-3Thread-4



Even by making SynchronizedMap we are getting wrong output when mutiple thread trying to update same Map key value. In above code we can see Thread-0 is missing. Next lets see how to thread safe when we edit under multi threading on same object. 

Example - 3 : Accessing updated HashMap with converted to SynchronizedMap & Synchronized block under Multi Threading.


public class HashMapTest implements Runnable{
 
 // Initializing new HashMap
 private Map<String, String> myMap = new HashMap<String, String>();
 
 public void run() {
  String threadName = Thread.currentThread().getName();
  // Synchronized block 
  synchronized (myMap) {
   String oldValue = myMap.get("myKey");
   String newValue = oldValue+threadName;
   myMap.put("myKey", newValue);
  }  
  System.out.println(threadName+" : "+myMap.get("myKey"));
 }
 
 public static void main(String[] args) {
  HashMapTest obj = new HashMapTest();
  
  // Adding values into HashMap
  obj.addValues();
  
  // Converting HashMap to Synchronized Map 
  obj.convertMapToSynMap();
  
  // Creating multiple Thread and starting
  for(int i=0;i<5;i++){
   new Thread(obj).start();
  }
  
 }
 public void convertMapToSynMap(){
  myMap = Collections.synchronizedMap(myMap);
 }
 public void addValues(){
  myMap.put("myKey", "Java Discover - ");
 }
}

OUTPUT:


Thread-0 : Java Discover - Thread-0Thread-1
Thread-1 : Java Discover - Thread-0Thread-1
Thread-2 : Java Discover - Thread-0Thread-1Thread-2Thread-3
Thread-3 : Java Discover - Thread-0Thread-1Thread-2Thread-3
Thread-4 : Java Discover - Thread-0Thread-1Thread-2Thread-3Thread-4

Now we see all Thread names are upended correctly from 0 to 5. Order doesn't matter since Thread will called according priority. 









How we can get the list of Key from HashMap?

Lets assume in interview you are been asked to list all the values in HashMap. HashMap contains around 1000 values and you have not given the list of keys to get the corresponding values. From HashMap to get the values first you need know the keys and later you can get the list of corresponding values.

            Today we will discuss about how to find the list of Key from HasMap. Before looking into direct program lets see some of the key features of HashMap and different between HashMap and HashTable. HashMap and HashTable will implements Map Interface but there are few difference between both of them where everyone needs to know.

HashMap is not synchronized where as HashTable is synchronized. If one who wants to use HashMap with synchronized then they the synchronize by using Java Collection utility as given below.
Since HashTable is synchronized by default it will slower than HashMap and performance wise HashMap will be better.
HashTable is defined in earlier version before Java Collections introduced.
HashMap will allow null key and value and where as in HashTable you cant place null key or value.
Iterator in HashMap is a fail-fast if any one tries to modify or remove the element from the HashMap and where as Enumeration in HashTable is not such. 
In HashMap value or key order will not be guarantee that will be same as inserted.

   

public class MyKeyList {
       
       public static void main(String[] args) {
               HashMap<String, String> hm = new MyKeyList().getHashMap();
                    
               Set<String> set = (Set<String>)hm.keySet();
               Iterator<String> itr = set.iterator();
               while(itr.hasNext()){
                       System.out.println(itr.next());
               }
               
               // Other way just by for loop as 
               for(Object key : hm.keySet()){
   System.out.println(hm.get(key));
  }

       }
       
       private HashMap<String, String> getHashMap(){
               HashMap<String, String> hm = new HashMap<String, String>();
               hm.put("one", "java");
               hm.put("four", ".NET");
               hm.put("two", "C");
               hm.put("five", "PHP");
               hm.put("three", "C++");
               return hm;
       }        
}


      In above program we have saved 5 values in HashMap and its been returned to main method and we have used Set and Iterator to get keys from the HashMap.
      Here need to remember about the function called ketSet() used to get the set of Keys from HashMap.



OUTPUT:



one
two
five
three
four



Hope you are clear now how to get list of Key from HashMap. You have any comments please drop it down.