Monday 27 March 2017

Internal Implementation of HashMap

Hash Map is one of the most used collection, though it will be surprising to know that maps themselves are not collections because they don... thumbnail 1 summary
Hash Map is one of the most used collection, though it will be surprising to know that maps themselves are not collections because they don't implement Collection interface. However collection view of a map can be obtained using entrySet() method. To obtain a collection-view of the keys, keySet() method can be used.

Internal working of the HashMap which is also a favourite Java Collections interview question
There are four things we should know about before going into the internals of how does HashMap work in Java -

1) HashMap works on the principal of hashing.
2) Map.Entry interface - This interface gives a map entry (key-value pair). HashMap in Java stores both key and value object, in bucket, as an object of Entry class which implements this nested interface Map.Entry.
3) hashCode() -HashMap provides put(key, value) for storing and get(key) method for retrieving Values from HashMap. When put() method is used to store (Key, Value) pair, HashMap implementation calls hashcode on Key object to calculate a hash that is used to find a bucket where Entry object will be stored. When get() method is used to retrieve value, again key object is used to calculate a hash which is used then to find a bucket where that particular key is stored.
4) equals() - equals() method is used to compare objects for equality. In case of HashMap key object is used for comparison, also using equals() method Map knows how to handle hashing collision (hashing collision means more than one key having the same hash value, thus assigned to the same bucket. In that case objects are stored in a linked list, refer figure for more clarity.
Where hashCode method helps in finding the bucket where that key is stored, equals method helps in finding the right key as there may be more than one key-value pair stored in a single bucket.
** Bucket term used here is actually an index of array, that array is called table in HashMap implementation. Thus table[0] is referred as bucket0, table[1] as bucket1 and so on.

How important it is to have a proper hash code and equals method can be seen through the help of the following program -

public class HashMapTest {
    public static void main(String[] args) {
        Map  cityMap = new HashMap();
        cityMap.put(new Key(1, "NY"),"New York City" );
        cityMap.put(new Key(2, "ND"), "New Delhi");
        cityMap.put(new Key(3, "NW"), "Newark");
        cityMap.put(new Key(4, "NP"), "Newport");

        System.out.println("size before iteration " + cityMap.size());
        Iterator  itr = cityMap.keySet().iterator();
        while (itr.hasNext()){
            System.out.println(cityMap.get(itr.next()));     
        }
        System.out.println("size after iteration " + cityMap.size());    
    }
 
}

// This class' object is used as key
// in the HashMap
class Key{
 int index;
 String Name;
 Key(int index, String Name){
  this.index = index;
  this.Name = Name;
 }
 
 @Override
 // A very bad implementation of hashcode
 // done here for illustrative purpose only 
 public int hashCode(){
  return 5;
 }
 
 @Override
 // A very bad implementation of equals
 // done here for illustrative purpose only 
 public boolean equals(Object obj){
  return true;
 }
 
}
Output

size before iteration 1
Newport
size after iteration 1

Lets get through the code to see what is happening, this will also help in understanding how put works internally.

Notice that I am inserting 4 values in the HashMap, still in the output it says size is 1 and iterating the map gives me the last inserted entry. Why is that?

Answer lies in, how hashCode() and equals() method are implemented for the key Class. Have a look at the hashCode() method of the class Key which always returns "5" and the equals() method which is always returning "true".

When a value is put into HashMap it calculates a hash using key object and for that it uses the hashCode() method of the key object class (or its parent class). Based on the calculated hash value HashMap implementation decides which bucket should store the particular Entry object.

In code the hashCode() method of the key class always returns "5". This effectively means calculated hash value, is same for all the entries inserted in the HashMap. Thus all the entries are stored in the same bucket.

Second thing, a HashMap implementation does is to use equals() method to see if the key is equal to any of the already inserted keys (Recall that there may be more than one entry in the same bucket). Note that, with in a bucket key-value pair entries (Entry objects) are stored in a linked-list (Refer figure for more clarity). In case hash is same, but equals() returns false (which essentially means more than one key having the same hash or hash collision) Entry objects are stored, with in the same bucket, in a linked-list.

In code, I am always returning true for equals() method so the HashMap implementation "thinks" that the keys are equal and overwrites the value. So, in a way using hashCode() and equals() I have "tricked" HashMap implementation to think that all the keys (even though different) are same, thus overwriting the values.

In a nutshell there are three scenarios in case of put() -

Using hashCode() method, hash value will be calculated. Using that hash it will be ascertained, in which bucket particular entry will be stored.
equals() method is used to find if such a key already exists in that bucket, if no then a new node is created with the map entry and stored within the same bucket. A linked-list is used to store those nodes.
If equals() method returns true, which means that the key already exists in the bucket. In that case, the new value will overwrite the old value for the matched key.

Pictorial representation of how Entry (key-value pair) objects will be stored in table array

How get() methods works internally

As we already know how Entry objects are stored in a bucket and what happens in the case of Hash Collision it is easy to understand what happens when key object is passed in the get method of the HashMap to retrieve a value.

Using the key again hash value will be calculated to determine the bucket where that Entry object is stored, in case there are more than one Entry object with in the same bucket stored as a linked-list equals() method will be used to find out the correct key. As soon as the matching key is found get() method will return the value object stored in the Entry object.

In case of null Key

As we know that HashMap also allows null, though there can only be one null key in HashMap. While storing the Entry object HashMap implementation checks if the key is null, in case key is null, it always map to bucket 0 as hash is not calculated for null keys.

HashMap changes in Java 8

Though HashMap implementation provides constant time performance O(1) for get() and put() method but that is in the ideal case when the Hash function distributes the objects evenly among the buckets.

But the performance may worsen in the case hashCode() used is not proper and there are lots of hash collisions. As we know now that in case of hash collision entry objects are stored as a node in a linked-list and equals() method is used to compare keys. That comparison to find the correct key with in a linked-list is a linear operation so in a worst case scenario the complexity becomes O(n).

To address this issue in Java 8 hash elements use balanced trees instead of linked lists after a certain threshold is reached. Which means HashMap starts with storing Entry objects in linked list but after the number of items in a hash becomes larger than a certain threshold, the hash will change from using a linked list to a balanced tree, this will improve the worst case performance from O(n) to O(log n).

Points to note -

HashMap works on the principal of hashing.
HashMap uses the hashCode() method to calculate a hash value. Hash value is calculated using the key object. This hash value is used to find the correct bucket where Entry object will be stored.
HashMap uses the equals() method to find the correct key whose value is to be retrieved in case of get() and to find if that key already exists or not in case of put().
Hashing collision means more than one key having the same hash value, in that case Entry objects are stored as a linked-list with in a same bucket.
With in a bucket values are stored as Entry objects which contain both key and value.
In Java 8 hash elements use balanced trees instead of linked lists after a certain threshold is reached while storing values. This improves the worst case performance from O(n) to O(log n).

Tuesday 14 March 2017

JDBC Interview Questions

1) What is JDBC? Java Database Connectivity (JDBC) is an application programming interface (API) for Java, which defines how a client m... thumbnail 1 summary
1) What is JDBC?

Java Database Connectivity (JDBC) is an application programming interface (API) for Java, which defines how a client may access a relational database. It provides methods to query and update data in a database. A JDBC-to-ODBC bridge enables connections to any ODBC-accessible data source in the Java virtual machine (JVM) host environment.

2) What is a JDBC Driver and what are the types of JDBC driver?

JDBC driver contains classes and interfaces that enables Java applications to interact with a database. There are 4 types of JDBC drivers:

Type 1 driver or JDBC-ODBC bridge driver – The JDBC-ODBC bridge driver uses native ODBC driver to connect to the database. It converts JDBC method calls into the ODBC function calls.
Type 2 driver or Native-API, partly Java driver – The Native API driver uses the client-side libraries of the database. The driver converts JDBC calls into database calls by using native API provided by database. This driver is database specific so once you switch from one database to another you need to change this driver. Native database library must be loaded on each client machine that uses this type of driver.
Type 3 driver or Network Protocol, pure Java driver – The Network Protocol driver uses server-side middleware that converts JDBC calls into the vendor-specific database protocol.
Type 4 driver or Native-protocol, pure Java driver – This is the most widely used driver nowadays. The driver converts JDBC calls directly into vendor-specific database protocol. Many of these protocols are proprietary, hence the database vendors themselves will be the primary source for this type of driver.

3) Which Driver should be Used?

If you are accessing one type of database, such as Oracle, Sybase, or IBM, the preferred driver type is 4.
If your Java application is accessing multiple types of databases at the same time, type 3 is the preferred driver.

4) What are the main steps to connect to database using JDBC connectivity?

Register the Driver

Class.forName() is used to load the driver class explicitly.

Example to register with JDBC-ODBC Driver

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

Create a Connection

getConnection() method of DriverManager class is used to create a connection.

getConnection(String url)
getConnection(String url, String username, String password)
getConnection(String url, Properties info)
Example establish connection with Oracle Driver

Connection con = DriverManager.getConnection
          ("jdbc:oracle:thin:@localhost:1521:XE","username","password");

Create SQL Statement

createStatement() method is invoked on current Connection object to create a SQL Statement.

public Statement createStatement() throws SQLException
Example to create a SQL statement

Statement s=con.createStatement();

Execute SQL Statement

executeQuery() method of Statement interface is used to execute SQL statements.

public ResultSet executeQuery(String query) throws SQLException
Example to execute a SQL statement

ResultSet rs=s.executeQuery("select * from user");
  while(rs.next())
  {
   System.out.println(rs.getString(1)+" "+rs.getString(2));
  }

Closing the connection

After executing SQL statement you need to close the connection and release the session. The close() method of Connection interface is used to close the connection.

public void close() throws SQLException
Example of closing a connection

con.close();

5) What are the types of statements in JDBC?

There are 3 JDBC statements.

Statement - Use the for general-purpose access to your database. Useful when you are using static SQL statements at runtime. The Statement interface cannot accept parameters. An object of Statement class can be created using Connection.createStatement() method.
PreparedStatement - Use the when you plan to use the SQL statements many times. The PreparedStatement interface accepts input parameters at runtime.A SQL statement is pre-compiled and stored in a PreparedStatement object. An object of PreparedStatement class can be created using Connection.prepareStatement() method.
CallableStatement - Use when you want to access the database stored procedures. The CallableStatement interface can also accept runtime input parameters.An object of CallableStatement class can be created using Connection.prepareCall() method.

6) What is JDBC Connection interface?

The Connection interface maintains a session with the database. It can be used for transaction management. It provides factory methods that returns the instance of Statement, PreparedStatement, CallableStatement and DatabaseMetaData.

7) What is JDBC ResultSet interface?

The ResultSet object represents a row of a table. It can be used to change the cursor pointer and get the information from the database.

8) What is JDBC ResultSetMetaData interface?

The ResultSetMetaData interface returns the information of table such as total number of columns, column name, column type etc.

9) What is database connection pooling? What are the advantages of using a connection pool?

Connection pooling is the mechanism by which we reuse connection objects which are used to make connection with the database. It allows multiple clients to share a cached set of connection objects. Getting connection and disconnecting are costly operation, which can affect the application performance, so we should avoid creating multiple connection objects during multiple database interactions.
A pool contains set of database connection objects which are already connected to the database, and any client who wants to use it can take it from pool and it can be returned back to the pool when done with using.
Apart from performance this also saves you resources as there may be limited database connections available for your application.

10) How do you iterate ResultSet in the reverse order?

You can traverse a ResultSet backwards if you have a scrollable resultset. You can get this by passing ResultSet.TYPE_SCROLL_INSENSITIVE and ResultSet.CONCUR_READ_ONLY parameters when creating the statement object.

Then you can use resultset.afterLast() to move the cursor to the end of the ResultSet object, just after the last row and traverse backwards using resultset.previous() method.

Here is a sample code.
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
                      ResultSet.CONCUR_READ_ONLY);
ResultSet resultSet = statement.executeQuery("select * from XX");
resultSet.afterLast();
while (resultSet.previous()) {
// do something
}

11) What are stored procedures? How to call stored procedure using JDBC API?

A stored procedure is a set of Structured Query Language (SQL) statements with an assigned name, which are pre-compiled and stored in a relational database management system as a group, so it can be reused and shared by multiple programs.Stored procedures can be compiled and executed with different parameters and results and may have any combination of IN/OUT parameters. Stored procedures can be called using CallableStatement class in JDBC API.
Example : 
CallableStatement cs = connection.prepareCall("{call STORED_PROCEDURE_NAME}");
ResultSet rs = cs.executeQuery();

12) What is DriverManager class?

The DriverManager class acts as an interface between user and drivers. It keeps track of the drivers that are available and handles establishing a connection between a database and the appropriate driver. The DriverManager class maintains a list of Driver classes that have registered themselves by calling the method DriverManager.registerDriver().

13) What is the use of setAutoCommit() method?

When a connection is created, it is in auto-commit mode by default. This means that each individual SQL statement is treated as a transaction and will be automatically committed right after it is executed. By setting auto-commit to false no SQL statements will be committed until you explicitly call the commit() method.

14) What is a “dirty read”?

There can be a situation where one transaction can change a value, and a second transaction can read this value before the original change has been committed or rolled back. This is known as a dirty read scenario because there is always the possibility that the first transaction may rollback the change, resulting in the second transaction having read an invalid value.

Sunday 12 March 2017

Java Collection Basic Questions Part 3

1) What is the importance of hashCode() and equals() methods? You must override hashCode() in every class that overrides equals(). Fail... thumbnail 1 summary
1) What is the importance of hashCode() and equals() methods?

You must override hashCode() in every class that overrides equals(). Failure to do so will result in a violation of the general contract for Object.hashCode(), which will prevent your class from functioning properly in conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable.
Let's try to understand it with an example of what would happen if we override equals() without overriding hashCode() and attempt to use a Map.
Say we have a class like this and that two objects of MyClass are equal if their importantField is equal (with hashCode() and equals() generated by eclipse)
public class MyClass {

    private final String importantField;
    private final String anotherField;

    public MyClass(final String equalField, final String anotherField) {
        this.importantField = equalField;
        this.anotherField = anotherField;
    }

    public String getEqualField() {
        return importantField;
    }

    public String getAnotherField() {
        return anotherField;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((importantField == null) ? 0 : importantField.hashCode());
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final MyClass other = (MyClass) obj;
        if (importantField == null) {
            if (other.importantField != null)
                return false;
        } else if (!importantField.equals(other.importantField))
            return false;
        return true;
    }

}

Override only equals

If only equals is overriden, then when you call myMap.put(first,someValue) first will hash to some bucket and when you call myMap.put(second,someOtherValue) it will hash to some other bucket (as they have a different hashCode). So, although they are equal, as they don't hash to the same bucket, the map can't realize it and both of them stay in the map.

Although it is not necessary to override equals() if we override hashCode(), let's see what would happen in this particular case where we know that two objects of MyClass are equal if their importantField is equal but we do not override equals().

Override only hashCode

Imagine you have this
MyClass first = new MyClass("a","first");
MyClass second = new MyClass("a","second");
If you only override hashCode then when you call myMap.put(first,someValue) it takes first, calculates its hashCode and stores it in a given bucket. Then when you call myMap.put(second,someOtherValue) it should replace first with second as per the Map Documentation because they are equal (according to the business requirement).

But the problem is that equals was not redefined, so when the map hashes second and iterates through the bucket looking if there is an object k such that second.equals(k) is true it won't find any as second.equals(first) will be false.

2) What is the difference between peek(),element() ,poll() and remove() method of the Queue interface ?

The peek() method retrieves the value of the first element of the queue without removing it from the queue. For each invocation of the method we always get the same value and its execution
does not affect the size of the queue. If the queue is empty the peek() method returns null.

The element() method behaves like peek(), so it again retrieves the value of the first element without removing it. Unlike peek ), however, if the list is empty element() throws a NoSuchElementException.

The poll() method retrieves the value of the first element of the queue by removing it from the queue. At each invocation it removes the first element of the list and if the list is already empty it returns null but does not throw any exception.

The remove() method behaves as the poll() method, so it removes the first element of the list and if the list is empty it throws a NoSuchElementException.

3) How to avoid ConcurrentModificationException while iterating a collection?

ConcurrentModificationException can come if two threads trying to modify one list at same time. E.g one thread is iterating over it and other is trying to remove elements from it. But more commonly it comes when you use Array List remove() method while iterating over list.
To avoid this always use iterator's  remove() method to delete elements while traversing.

4) Write java code showing insertion,deletion and retrieval of HashMap object ?

import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.Set;
public class Details {

   public static void main(String args[]) {

      /* This is how to declare HashMap */
      HashMap hmap = new HashMap();

      /*Adding elements to HashMap*/
      hmap.put(12, "Chaitanya");
      hmap.put(2, "Rahul");
      hmap.put(7, "Singh");
      hmap.put(49, "Ajeet");
      hmap.put(3, "Anuj");

      /* Display content using Iterator*/
      Set set = hmap.entrySet();
      Iterator itr1 = set.iterator();
      while(itr1.hasNext()) {
         Map.Entry entry = (Map.Entry)itr1.next();
         System.out.print("key is: "+ entry.getKey() + " & Value is: ");
         System.out.println(entry.getValue());
      }

      /* Get values based on key*/
      String var= hmap.get(2);
      System.out.println("Value at index 2 is: "+var);

      /* Remove values based on key*/
      hmap.remove(3);
      System.out.println("Map key and values after removal:");
      Set set2 = hmap.entrySet();
      Iterator itr = set2.iterator();
      while(itr.hasNext()) {
          Map.Entry entry1 = (Map.Entry)itr.next();
          System.out.print("Key is: "+entry1.getKey() + " & Value is: ");
          System.out.println(entry1.getValue());
       }

   }
}

Output:
key is: 49 & Value is: Ajeet
key is: 2 & Value is: Rahul
key is: 3 & Value is: Anuj
key is: 7 & Value is: Singh
key is: 12 & Value is: Chaitanya
Value at index 2 is: Rahul
Map key and values after removal:
Key is: 49 & Value is: Ajeet
Key is: 2 & Value is: Rahul
Key is: 7 & Value is: Singh
Key is: 12 & Value is: Chaitanya

5) What is UnsupportedOperationException?

UnsupportedOperationException is class which extends RuntimeException and this exception thrown to indicate that requested operation is not supported by API.
Reason is, when call java.util.Arrays.asList(String… a) method it returns fixed-size list backed by specified array so when you try to modify the list i.e. add or remove value from it will throw UnsupportedOperationException.
Below code will throw UnsupportedOperationException:

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class UnsupportedException {

 public static void main(String[] args) {

 String[] strings = { "Java", "Honk", "Test" };

 List list = Arrays.asList(strings);

 for (Iterator iterator = 
   list.iterator(); iterator.hasNext();) {
  String string = iterator.next();
  iterator.remove();
   }

 }

}

To fix UnsupportedOperationException use LinkedList constructor and pass collection object as parameter. Please see sample code below :
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class UnsupportedExceptionFix {

 public static void main(String[] args) {

 String[] strings = { "Java", "Honk", "Test" };

 List list2 = 
   new LinkedList(Arrays.asList(strings));
 for (Iterator iterator = 
   list2.iterator(); iterator.hasNext();) {
  String string = iterator.next();
  iterator.remove();
 }
 System.out.println("Removed all data from list");

 }

}

6) What is the difference between HashMap and ConcurrentHashMap ?

Significant difference between HashMap and ConcurrentHashMap is that ConcurrentHashMap is thread-safe and can be used in a concurrent environment without external synchronization. Though it doesn't provide the same level of synchronization as achieved by using Hashtable but it's enough for the most practical purpose.

HashMap can be synchronized by wrapping it on Collections.synchornizedMap(HashMap) which will return a collection which is almost equivalent to Hashtable, where every modification operation on Map is locked on whole Map object while in case of ConcurrentHashMap, thread-safety is achieved by dividing whole Map into different partition based upon Concurrency level and only locking particular portion instead of locking the whole Map.

ConcurrentHashMap is more scalable and performs better than Synchronized HashMap in the multi-threaded environment while in Single threaded environment both HashMap and ConcurrentHashMap gives comparable performance, where HashMap only slightly better.

Friday 3 March 2017

ExceptionHandling with MethodOverriding

An overriding method (the method of child class) can throw any unchecked exceptions, regardless of whether the overridden method (method... thumbnail 1 summary
An overriding method (the method of child class) can throw any unchecked exceptions, regardless of whether the overridden method (method of base class) throws exceptions or not. However the overriding method should not throw checked exceptions that are new or broader than the ones declared by the overridden method. The overriding method can throw those checked exceptions, which have less scope than the exception(s) declared in the overridden method.

If the superclass method does not declare an exception

1) Rule: If the superclass method does not declare an exception, subclass overridden method cannot declare the checked exception.

import java.io.*;  
class Parent{  
  void msg(){System.out.println("parent");}  
}  
  
class TestExceptionChild extends Parent{  
  void msg()throws IOException{  
    System.out.println("TestExceptionChild");  
  }  
  public static void main(String args[]){  
   Parent p=new TestExceptionChild();  
   p.msg();  
  }  
}  

2) Rule: If the superclass method does not declare an exception, subclass overridden method cannot declare the checked exception but can declare unchecked exception.

import java.io.*;  
class Parent{  
  void msg(){System.out.println("parent");}  
}  
  
class TestExceptionChild1 extends Parent{  
  void msg()throws ArithmeticException{  
    System.out.println("child");  
  }  
  public static void main(String args[]){  
   Parent p=new TestExceptionChild1();  
   p.msg();  
  }  
}  

If the superclass method declares an exception

1) Rule: If the superclass method declares an exception, subclass overridden method can declare same, subclass exception or no exception but cannot declare parent exception.

import java.io.*;  
class Parent{  
  void msg()throws ArithmeticException{System.out.println("parent");}  
}  
  
class TestExceptionChild2 extends Parent{  
  void msg()throws Exception{System.out.println("child");}  
  
  public static void main(String args[]){  
   Parent p=new TestExceptionChild2();  
   try{  
   p.msg();  
   }catch(Exception e){}  
  }  
}  

Wednesday 1 March 2017

Java Collection Basic Questions Part 2

The Java Collections API's provide Java developers with a set of classes and interfaces that makes it easier to handle collections of... thumbnail 1 summary
The Java Collections API's provide Java developers with a set of classes and interfaces that makes it easier to handle collections of objects.


1) What is difference between an ArrayList and a vector?

a) Synchronization: ArrayList is non-synchronized which means multiple threads can work on ArrayList at the same time. For e.g. if one thread is performing an add operation on ArrayList, there can be an another thread performing remove operation on ArrayList at the same time in a multithreaded environment

while Vector is synchronized. This means if one thread is working on Vector, no other thread can get a hold of it. Unlike ArrayList, only one thread can perform an operation on vector at a time.

b) Resize: A Vector defaults to doubling size of its array . While when you insert an element into the ArrayList ,      it increases
its Array size by 50% .

c) Performance: Vector is slow as it is thread safe . In comparison ArrayList is fast as it is non synchronized . Thus     in ArrayList two or more threads  can access the code at the same time  , while Vector is limited to one thread at a time.

d) fail-fast: First let me explain what is fail-fast: If the collection (ArrayList, vector etc) gets structurally modified by any means, except the add or remove methods of iterator, after creation of iterator then the iterator will throw ConcurrentModificationException. Structural modification refers to the addition or deletion of elements from the collection.

As per the Vector javadoc the Enumeration returned by Vector is not fail-fast. On the other side the iterator and listIterator returned by ArrayList are fail-fast.

e) Who belongs to collection framework really? The vector was not the part of collection framework, it has been included in collections later. It can be considered as Legacy code. There is nothing about Vector which List collection cannot do. Therefore Vector should be avoided. If there is a need of thread-safe operation make ArrayList synchronized as discussed in the next section of this post or use CopyOnWriteArrayList which is a thread-safe variant of ArrayList.

2) What is different between Iterator and ListIterator?

a) Iterator is used for traversing List and Set both.
While ListIterator is used to traverse List only.

b) We can traverse in only forward direction using Iterator.
Using ListIterator, we can traverse a List in both the directions (forward and Backward).

c) We cannot obtain indexes while using Iterator
We can obtain indexes at any point of time while traversing a list using ListIterator using nextIndex() and previousIndex() are used for this purpose.

d) We cannot add element to collection while traversing it using Iterator, it throws ConcurrentModificationException when you try to do it.
We can add element at any point of time while traversing a list using ListIterator.

e) We cannot replace the existing element value when using Iterator.
By using set(E e) method of ListIterator we can replace the last element returned by next() or previous() methods.

f) Methods of Iterator:
  • hasNext()
  • next()
  • remove()

Methods of ListIterator:
  • add(E e)
  • hasNext()
  • hasPrevious()
  • next()
  • nextIndex()
  • previous()
  • previousIndex()
  • remove()
  • set(E e)

3) What is difference between fail-fast and fail-safe?

a)Fail-fast Iterator throws ConcurrentModfiicationException as soon as they detect any structural change in collection during iteration, basically which changes the modCount variable hold by Iterator. While fail-safe iterator doesn't throw CME.

b)Fail-fast iterator traverse over original collection class while fail-safe iterator traverse over a copy or view of original collection. That's why they don't detect any change on original collection classes and this also means that you could operate with stale value.

c)Iterators from Java 1.4 Collection classes e.g. ArrayList, HashSet and Vector are fail-fast while Iterators returned by concurrent collection classes e.g. CopyOnWriteArrayList or CopyOnWriteArraySet are fail-safe.

d)Fail fast iterator works in live data but become invalid when data is modified while fail-safe iterator are weekly consistent.

4) How  Fail  Fast Iterator  come to know that the internal structure is modified ?

The usual way is like this: The collection object keeps a "modCount(version)" variable that is incremented on every modification, and the iterator remembers the last "modification count" that it remembers (either from when the iterator was created, or the last modification that was done through the iterator). Every time the iterator is used, it checks its modification count against the collection's, and if it is different, it knows someone modified the collection without using it, and throws the exception.

Note : The 'remove' method also checks the count but, if successful, resets the count to the new value. It does this so that you can use the 'remove' method to remove an entry WITHOUT getting the exception.

5) What is the difference between ArrayList and LinkedList?

a)Search: ArrayList search operation is pretty fast compared to the LinkedList search operation. get(int index) in ArrayList gives the performance of O(1) while LinkedList performance is O(n).

Reason: ArrayList maintains index based system for its elements as it uses array data structure implicitly which makes it faster for searching an element in the list. On the other side LinkedList implements doubly linked list which requires the traversal through all the elements for searching an element.

b)Deletion: LinkedList remove operation gives O(1) performance while ArrayList gives variable performance: O(n) in worst case (while removing first element) and O(1) in best case (While removing last element).

c)Conclusion: LinkedList element deletion is faster compared to ArrayList.

Reason: LinkedList’s each element maintains two pointers (addresses) which points to the both neighbor elements in the list. Hence removal only requires change in the pointer location in the two neighbor nodes (elements) of the node which is going to be removed. While In ArrayList all the elements need to be shifted to fill out the space created by removed element.

d)Inserts Performance: LinkedList add method gives O(1) performance while ArrayList gives O(n) in worst case. Reason is same as explained for remove.

e)Memory Overhead: ArrayList maintains indexes and element data while LinkedList maintains element data and two pointers for neighbor nodes hence the memory consumption is high in LinkedList comparatively.

6) What is the difference between List and Set?

a)Ordering : List is an ordered collection it maintains the insertion order, which means upon displaying the list content it will display the elements in the same order in which they got inserted into the list.
Set is an unordered collection, it doesn’t maintain any order. There are few implementations of Set which maintains the order such as LinkedHashSet (It maintains the elements in insertion order).

b)DublicateValues : List allows duplicates while Set doesn’t allow duplicate elements. All the elements of a Set should be unique if you try to insert the duplicate element in Set it would replace the existing value.

c)Null Values : List allows any number of null values. Set can have only a single null value at most.

d)Iterator : ListIterator can be used to traverse a List in both the directions(forward and backward) However it can not be used to traverse a Set. We can use Iterator (It works with List too) to traverse a Set.

e)Legacy Class : List interface has one legacy class called Vector whereas Set interface does not have any legacy class.

7) What is the difference between HashSet and TreeSet?

a)Ordering : HashSet stores the object in random order . There is no guarantee that the element will be printed first in the output  which one is inserted first in the HashSet  .
Elements are sorted according to the natural ordering of its elements in TreeSet. If the objects can not be sorted in natural order than use compareTo() method to sort the elements of TreeSet object .

b)Null value : Null value can not be stored in TreeSet while in HashSet it is possible. If one try to store null object in TreeSet object , it will throw Null Pointer Exception.

c)Performance : HashSet take constant time performance for the basic operations like add, remove contains and size.While TreeSet guarantees log(n) time cost for the basic operations (add,remove,contains).

d)Speed : HashSet is much faster than TreeSet,as performance time of HashSet is constant against the log time of TreeSet for most operations (add,remove ,contains and size).

e)Internal implementation : HashSet are internally backed by hashmap. While TreeSet is backed by a TreeMap.

f)Functionality : TreeSet is rich in functionality as compare to HashSet. Functions like pollFirst(),pollLast(),first(),last(),ceiling(),lower() etc. makes TreeSet easier to use than HashSet.

g)Comparision : HashSet uses equals() method for comparison in java while TreeSet uses compareTo() method for maintaining ordering .

8) What is the difference between HashSet and HashMap?

a)Adding or Storing mechanism : HashMap internally uses hashing to add or store objects. HashSet internally uses HashMap object to add or store the objects.

b)Number of objects during add(put) operation :  HashMap requires two objects put(K key , V Value) to add an element to HashMap object.
HashSet requires only one object add(Object o).

c)Performance : HashMap is faster than HashSet because unique key is used to access object .

d)Storage : HashMap Stores data in form of  key-value pair while HashSet Store only objects.

e)Internal implementation : HashSet are internally backed by hashmap. HashMap  is an implementation of Map interface.

f)Duplicates  :  HashSet does not allow duplicate values.If the HashMap previously contain the mapping for the key, the old value is replaced. HashMap  does not allow duplicate keys but allow dublicate values.

9) What is the difference between HashMap and TreeMap?

a)Ordering : HashMap stores the object in random order . There is no guarantee that the element will be printed first in the output  which one is inserted first in the HashMap  .
Elements are sorted according to the natural ordering of its elements in TreeMap. If the objects can not be sorted in natural order than use compareTo() method to sort the elements of TreeMap object .

b)Implementation : Internal HashMap implementation use Hashing. TreeMap internally uses Red-Black tree implementation.

c)Null keys and Null value : TreeMap can not contain null keys but may contain many null values. HashMap can store one null key and many  null values.

d)Performance : HashMap  take constant time performance for the basic operations like get and put i.e O(1). TreeMap provides guaranteed log(n) time cost for the get and put method. Hence HashMap is much faster than TreeMap, as performance time of HashMap is constant against the log time TreeMap for most operations.

e)Interfaces implemented : HashMap implements Map interface while TreeMap implements NavigableMap interface.

10) What is the difference between HashMap and Hashtable?

a)Synchronization or Thread Safe : Hashtable is synchronized, whereas HashMap is not. This makes HashMap better for non-threaded applications, as unsynchronized Objects typically perform better than synchronized ones.

b)Null keys and null values : Hashtable does not allow null keys or values.  HashMap allows one null key and any number of null values.

c)Iterating the values :  Hashmap object values are iterated by using iterator .HashTable is the only class other than vector which uses enumerator to iterate the values of HashTable object.

11) What is the difference between Comparable and Comparator?

a)Sort sequence : Comparable provides single sorting sequence. In other words, we can sort the collection on the basis of single element such as id or name or price etc. Comparator provides multiple sorting sequence. In other words, we can sort the collection on the basis of multiple elements such as id, name and price etc.

b)Methods Used : Comparable provides compareTo() method to sort elements. Comparator provides compare() method to sort elements.

c)Modify Classes : Comparable affects the original class i.e. actual class is modified. Comparator doesn't affect the original class i.e. actual class is not modified.

d)Package : Comparable is found in java.lang package. Comparator is found in java.util package.

e)Objects needed for Comparision : If you see then logical difference between these two is Comparator in Java compare two objects provided to it , while Comparable interface compares "this" reference with the object specified. So only one object is provided which is then compared to "this" reference.

f)Example : We can sort the list elements of Comparable type by Collections.sort(List) method. We can sort the list elements of Comparable type by Collections.sort(List) method.

12) What is difference between Synchronized and Concurrent Collections in Java?

Synchronised collections are the "thread safe" , which addresses synchronization by making all the public methods of the collection "Synchronized". E.G : Collections.synchronizedMap(Map) will be a synchronized map and can be modified by one thread at a time. Synchronized : like a toilet, the object can be used by only one person (thread). However it is sharable even only one person can use it at one time.

Concurrent collections like ConcurrentHashMap are designed for concurrent access from Multiple threads. Instead of synchronizing every method on a common lock, restricting access to a single thread at a time, it uses a finer-grained locking mechanism called lock striping .For example ConcurrentHashMap introduced concept of segmentation, only certain part of it get locked to provide thread safety so many other readers can still access map without waiting for iteration to complete. Concurrent : like pond, where many person (threads) can solve their different needs. Like washerman washes, some take bath and so on.