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

How to convert list to read-only list in Java?

 
By using Collections class we can convert List to read-only List. This can done by using Collections.unmodifiableList(list) function from Collections class. By this we can't add or remove any element from the List. Not only List we can make other Collection Objects like Map, Set also to read-only as like below.

Collections.unmodifiableMap(map);
Collections.unmodifiableSet(set);
Collections.unmodifiableSortedMap(sortedMap);
Collections.unmodifiableSortedSet(sortedSet);

Lets see small example how to convert list to read-only list.


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

public class ReadOnlyList {

 public static void main(String[] args) {
  
  List<String> list = new ArrayList<String>();
  list.add("java");
  list.add("discover");
  list.add("threads");
  list.add("oops");
  list.add("servlet");
  
  System.out.println("LIST : "+list);
  
  // Removing "oops" from from list
  list.remove(3);
  
  System.out.println("LIST : "+list);
    
  // Making list to read-only
  list = Collections.unmodifiableList(list);

  // trying to removing "threds" from list
  list.remove(2);
    
  System.out.println("LIST : "+list);
 }
}


OUTPUT:


LIST : [java, discover, threads, oops, servlet]
LIST : [java, discover, threads, servlet]
Exception in thread "main" java.lang.UnsupportedOperationException


If we seen in above program we have added 5 values in list and we have removed 1 value "oops" from the list. Next we have converted list to read-only list by using unmodifiableList() method. Later when we try to remove "discover" value it throws UnsupportedOperationException because of read-only list. Even we can't add any value to this list. 




Vector and ArrayList

 
In this tutorial we will see about Vector and ArrayList in java. Both Vector and ArrayList shares common data structure "Array" internally.

Synchronized and non-synchronized
By default Vector is Synchronized and ArrayList is not Synchronized. By this for Thread safe we can use Vector and for non-thread safe we can use ArrayList. Even ArrayList can be converted to synchronized by Collections class using "Collections.synchronizedList(list)"


Vector in Collection API
Vector defined in first JDK version and later from Java 2 platform Vector got added with Java Collection API. Vector has been retrofitted to implement List Interface.
Once Vector added in Collection API, older methods in Vector class got updated to implement List Interface. Below are the methods got updated from Older version to new methods.


Old Vector MethodsNew Vector Methods
void addElement(Object)boolean add(Object)
boolean removeElement(Object)boolean remove(Object)
void removeElementAt(int)void remove(int)
void insertElementAt(Object, int)void add(index, Object)
Object elementAt(int)Object get(int)
Enumeration elements()Iterator iterator()
ListIterator listIterator()
void copyInto(Object[])Object[] toArray()
void removeAllElements()void clear()
void setElementAt(int)Object set(int, Object)


Where to use Vector and ArrayList
By performance wise ArrayList will be better in case of non synchronized operations and when we need for thread-safe operation then we need to opt for Vector.

Size
Both Vector and ArrayList will re-size dynamically. Vector will double the size of its array automatically when its full, where as ArrayList will increase by half of its array size.









TreeMap using custom object sorting

 
We know that by default TreeMap will sort the values using key. Suppose if we need to sort the TreeMap using object stored in key part then we need to implement the Comparator interface and we need to @Override compare() method which will sort 2 Objects of key path and will give us the sorted output. 

Below single example will show you how to use custom Object sorting in TreeMap. TreeMap will take "Worker class instance" as key and "String name" as value. Where we need to sort the values using key based on the member variables in the Worker class. 

Class "MyNameComp" which implements the Comparator interface on "Worker" class and used to sort TreeMap based on name or salary. Below example will gives you sort on salary. Suppose if we need output based on name sorted then we need to un-comment "return obj1.getName().compareTo(obj2.getName());"



public class TreeMapUsingObjectSorting {
 
 public static void main(String a[]){
  TreeMap<Worker,String> map = new TreeMap<Worker, String>(new MyNameComp());
  map.put(new Worker("david",5000), "david");
  map.put(new Worker("joy",2000), "joy");
  map.put(new Worker("abel",7000), "abel");
  map.put(new Worker("ruby",9000), "ruby");
  
  for (Map.Entry<Worker, String> entry : map.entrySet()) {
   System.out.println("KEY : "+ entry.getKey() +" \t VALUE : "+entry.getValue());
  }
 }
}




public class Worker{
    
    private String name;
    private int salary;
    
    public Worker(String name, int salary){
        this.name = name;
        this.salary = salary;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getSalary() {
        return salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
    /* Called by entry.getKey() 
       Overriding toString() method from super class Object
       Since key is Object we are return our own key value
    */
    public String toString(){
     //return super.toString();
     return "("+this.name+":"+this.salary+")";
    }
}




public class MyNameComp implements Comparator<Worker>{

 @Override
 public int compare(Worker obj1, Worker obj2) {
        
  // Sort TreeMap based on name
  //return obj1.getName().compareTo(obj2.getName());
  
  // Sort TreeMap based on salary
  if(obj1.getSalary() > obj2.getSalary()) return 1;
  else if(obj1.getSalary() < obj2.getSalary()) return -1;
  else return 0;
    } 
}

OUTPUT:


KEY : (joy:2000)   VALUE : joy
KEY : (david:5000)   VALUE : david
KEY : (abel:7000)   VALUE : abel
KEY : (ruby:9000)   VALUE : ruby









Difference between Iterator and Enumeration in Java?

In our last tutorial we have seen difference between Iterator and ListIterator. In this tutorial we will see about difference between Iterator and Enumeration in Java. Both Iterator and Enumeration are used to traverse elements in the Collection Object. Differences are,
  • Enumeration are introduced in older Java version and Iterator introduced in later version with additional features.
  • By Enumeration allows only traverse through elements, where as by Iterator we can traverse and also we can remove elements from the Collection Object.
  • Iterator is more secure and safe compared to Enumeration since its thread safe and won't allow others threads to modify the elements in Collection Object while some Thread is Iterating. On that case it will give ConcurrentModificationException

Finally we can decide if we are going for Read-only then we can for Enumeration else we can go for Iterator.

Mainly there are two types of Iterator in Java and they fail-fast and fail-safe Iterators. fail-fast iterators are those who throw ConcurrentModificationException if collection Object is modified when other Thread iterating on same Object. Fail-safe Iterator works on copying collection Object and won't work on original Object and its safe compared to fail-fast.    

Lets see example for both Iterator and Enumeration in Java



public class IteratorEnumerationTest {
 
 public static void main(String[] args) {
  
  ArrayList<String> myList = new ArrayList<String>();
  
  myList.add("one");
  myList.add("two");
  myList.add("three");
  myList.add("four");
  myList.add("five");
  
  Iterator<String> itr = myList.iterator();
  System.out.println("THROUGH ITERATOR : ");
  while(itr.hasNext()){
   System.out.print(itr.next()+", ");   
  }
  
  Vector<String> vec = new Vector<String>(myList);

  Enumeration<String> enu = vec.elements();
  
  System.out.println("\n\nTHROUGH ENUMERATION : ");
  while(enu.hasMoreElements()){
   System.out.print(enu.nextElement()+", ");
  }
 } 
}



OUTPUT:


THROUGH ITERATOR : 
one, two, three, four, five, 

THROUGH ENUMERATION : 
one, two, three, four, five, 










Difference between Iterator and ListIterator in Java?

In this tutorial we will see about difference between java.util.Iterator and java.util.ListIterator interfaces. Both interface are used to traverse values from the collection Object. But the differences are 

  • Iterator can traverse only in forward direction, where as ListIterator can traverse in both (bidirectional). 
  • Iterator can be used to traverse values in List and Set collections, where as ListIterator is used to traverse only in List.
  • ListIterator derived from Iterator interface and contains functions like remove(), previous(), next(), nextIndex(), previousIndex() etc.,


Lets see examples for both Iterator and ListIterator as how its used on Collection Object. 

Iterator Example:


public class IteratorTest {
 
 public static void main(String[] args) {
  List<String> myList = new ArrayList<String>();
  myList.add("java");
  myList.add("collections");
  myList.add("API");
  myList.add("important");
  myList.add("interview");
  myList.add("questions");
  
  System.out.println("LIST BEFORE REMOVE : "+myList);
  
  Iterator<String> itr = myList.iterator();
  while(itr.hasNext()){
   String val = itr.next();
   if(val.equals("API")){
    // Removing "API" value from ArrayList
    itr.remove();
   }   
  }  
  System.out.println("LIST AFTER REMOVE : "+myList);
 } 
}

OUTPUT:


LIST BEFORE REMOVE : [java, collections, API, important, interview, questions]
LIST AFTER REMOVE : [java, collections, important, interview, questions]


ListIterator Example:


public class ListIteratorTest {
 
 public static void main(String[] args) {
  List<String> myList = new ArrayList<String>();
  myList.add("java");
  myList.add("collections");
  myList.add("API");
  myList.add("important");
  myList.add("interview");
  myList.add("questions");
  
  System.out.println("LIST : "+myList);
  
  ListIterator<String> itr = myList.listIterator();
  while(itr.hasNext()){
   String val=itr.next();   
   if(val.equals("API")){
    // moving to previous element
    itr.previous();
    System.out.println("PREVIOUS VALUE : "+myList.get(itr.previousIndex()));
    // moving to forward element
    itr.next();
    System.out.println("NEXT VALUE     : "+myList.get(itr.nextIndex()));
   }
  }
 } 
}

OUTPUT:


LIST : [java, collections, API, important, interview, questions]
PREVIOUS VALUE : collections
NEXT VALUE     : important









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.