Java Interview QuestionsNo Comments

Advanced Collections

1. What is the difference between synchronized and concurrent collections in Java?

Synchronized collections are implemented using synchronized methods and synchronized blocks. Only one thread can executing any of the synchronized code at a given point in time. This places severe restrictions on the concurrency of threads – thereby affecting performance of the application. All the pre Java 5 synchronized collections (HashTable & Vector, for example) use this approach.

Post Java 5, collections using new approaches to synchronization are available in Java. These are called concurrent collections. More details below.


2. Explain about the new concurrent collections in Java?

Post Java 5, collections using new approaches to synchronization are available in Java. These are called concurrent collections. Examples of new approaches are :

• Copy on Write

• Compare and Swap

• Locks

These new approaches to concurrency provide better performance in specific context’s. We would discuss each of these approaches in detail below.


3. Explain about CopyOnWrite concurrent collections approach?

Important points about Copy on Write approach :-

• All values in collection are stored in an internal immutable (not-changeable) array. A new array is created if there is any modification to the collection.
• Read operations are not synchronized. Only write operations are synchronized.

Copy on Write approach is used in scenarios where reads greatly out number write’s on a collection. CopyOnWriteArrayList & CopyOnWriteArraySet are implementations of this approach. Copy on Write collections are typically used in Subject – Observer scenarios, where the observers very rarely change. Most frequent operations would be iterating around the observers and notifying them.

Example : CopyOnWriteArrayList : public boolean add(E e)


4. What is CompareAndSwap approach?

Compare and Swap is one of the new approaches (Java 5) introduced in java to handle synchronization. In traditional approach, a method which modifies a member variable used by multiple threads is completely synchronized – to prevent other threads accessing stale value.

In compare and swap approach, instead of synchronizing entire method, the value of the member variable before calculation is cached. After the calculation, the cached value is compared with the current value of member variable. If the value is not modified, the calculated result is stored into the member variable. If another thread has modified the value, then the calculation can be performed again. Or skipped – as the need might be.

ConcurrentLinkedQueue uses this approach.


5. What is a Lock? How is it different from using synchronized approach?

CopyOnWriteArrayList : final ReentrantLock lock = this.lock;

When 10 methods are declared as synchronized, only one of them is executed by any of the threads at any point in time. This has severe performance impact.

Another new approach introduced in Java 5 is to use lock and unlock methods. Lock and unlock methods are used to divide methods into different blocks and help enhance concurrency. The 10 methods can be divided into different blocks, which can be synchronized based on different variables.


5. What is initial capacity of a Java Collection?

Extract from the reference : http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html. An instance of HashMap has two parameters that affect its performance: initial capacity and load factor. The capacity is the number of buckets in the hash table, and the initial capacity is simply the capacity at the time the hash table is created. The load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased.

When the number of entries in the hash table exceeds the product of the load factor and the current capacity, the hash table is rehashed (that is, internal data structures are rebuilt) so that the hash table has approximately twice the number of buckets.

As a general rule, the default load factor (.75) offers a good tradeoff between time and space costs. Higher values decrease the space overhead but increase the lookup cost (reflected in most of the operations of the HashMap class, including get and put).

The expected number of entries in the map and its load factor should be taken into account when setting its initial capacity, so as to minimize the number of rehash operations.


6. When does a Java collection throw UnsupportedOperationException?

All Java Collections extend Collection interface. So, they have to implement all the methods in the Collection interface. However, certain Java collections are optimized to be used in specific conditions and do not support all the Collection operations (methods). When an unsupported operation is called on a Collection, the Collection Implementation would throw an UnsupportedOperationException.

Arrays.asList returns a fixed-size list backed by the specified array. When an attempt is made to add or remove from this collection an UnsupportedOperationException is thrown. Below code throws UnsupportedOperationException.

List < String > list = Arrays.asList(new String[] {"ac","bddefe"});
list.remove(); //throws	UnsupportedOperationException

7. What is difference between fail-safe and fail-fast iterators?

Fail Fast Iterators throw a ConcurrentModificationException if there is a modification to the underlying collection is modified. This was the default behavior of the synchronized collections of pre Java 5 age.

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class FailFast {

    public static void main(String[] args) {
        Map < String, String > map = new HashMap < String, String > ();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value3");

        Iterator < String > iterator = map.keySet().iterator();

        while (iterator.hasNext()) {
            System.out.println(map.get(iterator.next()));
            map.put("key4", "value4");
        }

    }

}

Fail Safe Iterators do not throw exceptions even when there are changes in the collection. This is the default behavior of the concurrent collections, introduced since Java 5.

Fail Safe Iterator makes copy of the internal data structure (object array) and iterates over the copied data structure.

Fail Safe is efficient when traversal operations vastly outnumber mutations.

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;

public class FailSafe {

    public static void main(String[] args) {
        ConcurrentHashMap < String, String > map = new ConcurrentHashMap < String, String > ();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value3");
        Iterator < String > iterator = map.keySet().iterator();

        while (iterator.hasNext()) {
            System.out.println(map.get(iterator.next()));
            map.put("key4", "value4");
        }

    }

}

8. What are atomic operations in Java?

Atomic Access Java Tutorial states “In programming, an atomic action is one that effectively happens all at once. An atomic action cannot stop in the middle: it either happens completely, or it doesn’t happen at all. No side effects of an atomic action are visible until the action is complete”.

Let’s assume we are writing a multi threaded program. Let’s create an int variable i. Even a small operation, like i++ (increment), is not thread safe. i++ operation involves three steps.

1. Read the value which is currently stored in i

2. Add one to it (atomic operation).

3. Store it in i

In a multi-threaded environment, there can be unexpected results. For example, if thread1 is reading the value (step 1) and immediately after thread2 stores the value (step 3).

To prevent these, Java provides atomic operations. Atomic operations are performed as a single unit without interference from other threads ensuring data consistency.

A good example is AtomicInteger. To increment a value of AtomicInteger, we use the incrementAndGet() method. Java ensures this operation is Atomic.


9. What is BlockingQueue in Java?

BlockingQueue interface is introduced in Java specifically to address specific needs of some Producer Consumer scenarios. BlockedQueue allows the consumer to wait (for a specified time or infinitely) for an element to become available.