Java Collections interview questions and answers

Here is the list of Java Collections interview questions. These questions have been asked over time and are still being asked in interviews. It is good to go through them to understand the various concepts in Collections.

Java Collections Interview Questions and Answers

What is a HashSet and how does it work internally in Java?

HashSet is an implementation for the Set interface of Java. It internally uses a HashMap to store and retrieve data. It is not a synchronized data structure. So, if multiple threads access and then modify contents of a HashSet, then it is the responsibility of the developer to synchronize that part of the code to make sure that the data is not corrupted. If you look at HashMap API in oracle documentation, you can see the following:
public V put(K key, V value)

The map.put returns the original value for the key if present or returns null otherwise.
public V remove(Object key)

The value V will be the value associated with the key if it was present in the hashmap or null otherwise.
HashSet simply adds an empty String to the value part of the HashMap when we try to insert an element into it.
So, if HashSet.add(key) is called, it will internally call map.put(key,””) only if the value returned by the operation is null. Otherwise, it will not add the value to the HashSet.If the HashSet.remove(key) is called, it will remove the value from the map only if the value is present in the map. Based on the success of the above operations, boolean value true or false is returned for HashSet.add(object) and HashSet.remove(Object).
The implementation of the HashSet can be vaguely written like this:

import java.io.Serializable;
import java.util.*;

public class HashSet extends AbstractSet implements Set, Cloneable, Serializable {
	private transient HashMap<T, String> map;

	public HashSet() {
		this(HashMap.DEFAULT_CAPACITY, HashMap.DEFAULT_LOAD_FACTOR);
	}

	public HashSet(int capacity, int loadFactor) {
		this.map = new HashMap<T, String>(capacity, loadFactor);
	}

	public boolean add(E element) {
		return map.put(element, "") == null;
	}

	public boolean remove(Object element) {
		return (map.remove(element) != null);
	}
	//	further supporting methods for implemented interfaces
	//  or abstract methods here...
}


Here are the javadocs for HashSet

What is the difference between Collections.synchronizedMap and ConcurrentMap?

Both the classes are thread-safe. The Collections.synchronizedMap(Map<K,V> map) returns a map that has a lock over the full object. Only one thread which has acquired the lock over the object can modify the map.
In the case of ConcurrentMap, the map is divided into more than one regions, each of which has a separate lock. So, multiple threads can access/modify the ConcurrentMap even though only one thread can do so per region of the Map.

What is the difference between a CheckedMap and an UnmodifiableMap?

Collections.checkedMap(map) will return a map that will throw ClassCastException if you try to add a wrong type of object into it. It will throw ClassCastException if you try to modify existing values also.
Collections.unmodifiableMap is used in case you need to give a read-only view of the data of the map. This is most commonly used in case of DAO’s of various databases where you need to read a set of properties as key-value pairs and present it to the user without letting the user modify them. When you try to add correct type of data or modify existing data, it will throw UnsupportedOperationException.

What are fail-fast and fail-safe iterators?

Fail-fast iterators throw a ConcurrentModificationException as soon as they see that the user is trying to modify the collection during the iteration process. This is done so that the value of underlying data structure does not get corrupted. An example of this is an Iterator for ArrayList.
Fail-safe iterators do not throw the above-said exception as the iterators iterate over a copy of the actual data structure rather than the original data structure. Example for this is iterator of CopyOnWriteArrayList. As the name suggests, the iterator will be iterating over a copy of the list rather than the original one. One drawback of this would be that it is not guaranteed to show updated values to the thread which is manipulating the data structure as it would be working on a copy of the actual data structure.

 How should you design your own class which shall be used as a key in a HashMap?

If you want to design your own class, whose object shall be used as a key in a map, you need to override the hashCode and equals methods of the superclass Object. They need to follow the hashcode and equals contract, ie, if obj1.equals(obj2) returns true, then obj1.hashCode() should be same as obj2.hashCode().

What is a NavigableMap?

NavigableMap was introduced in Java1.6. This is a sorted map with navigation capabilities added to it. Since Java 1.6, TreeMap implements NavigableMap.
The methods added to NavigableMap interface allows you to search through the Map. It has methods like lowerKey() and floorKey() which gives corresponding keys less than and less than or equal to the specified key. ceilingKey() and higherKey() are the methods which give keys greater than or equal to and greater than the specified key respectively. Similar methods are there to get Map.Entry objects as well.
Another use case of the NavigableMap is to get a submap of the given Map based on the delimiters specified. The submap thus obtained is actually a backed collection. If we add a value to the original map or the submap which is in the range of the submap, the result is appended to both the maps.
Let us see that with an example program:

import java.util.*;

public class TreeMapTest{
	public static void main(String[] args){
		TreeMap<String,String> treeMap = new TreeMap<String, String>();
		treeMap.put("a", "apple");
		treeMap.put("c", "cherry");
		treeMap.put("p", "pear");
		// create a submap here with limits c till n
		SortedMap<String, String> subMap = treeMap.subMap("c", "n");
		System.out.println("Value of treeMap and subMap before modification...");
		System.out.println(treeMap);
		System.out.println(subMap);
		subMap.put("m", "mango");
		System.out.println("Value of treeMap and subMap after modification...");
		System.out.println(treeMap);
		System.out.println(subMap);
		
		
	}
}

Output:

Value of treeMap and subMap before modification...
{a=apple, c=cherry, p=pear}
{c=cherry}
Value of treeMap and subMap after modification...
{a=apple, c=cherry, m=mango, p=pear}
{c=cherry, m=mango}

What is the difference between Iterator and Enumeration?

Enumeration and Iterator interfaces are found in java.util package. Both are used for traversing the collection. But there are subtle differences between both of them which are listed below:

  • Using Iterator, you can remove an object from the collection while traversing. This is not possible using Enumeration. In the case of Enumeration, only traversal is possible.
  • Enumeration is an interface released during early Java days when collections like Vector, HashTable, etc., were predominantly in use. Iterator was released later along with other famous members of the collections framework like ArrayList, HashSet, etc.
  • Methods in Enumeration are: hasMoreElements() and nextElement(). Methods in Iterator are: hasNext(), next() and remove().
  • Oracle recommends using Iterator over Enumeration.

How can we reverse a List?

Collections class contains a static method that allows you to reverse a given list. Collections.reverse(list) can be called to achieve this.

What is the difference between HashMap and a HashTable?

Although both HashMap and HashTable are implementations of the Map interface, there are small differences between them which are as follows:

  • HashMap is not thread-safe but HashTable is threadsafe and synchronized.
  • HashMap allows one null key and several null values but HashTable does not allow any null keys or values.
  • HashMap can be iterated only using java.util.Iterator. HashTable provides Enumeration as well as Iterator for traversal. Enumeration is still supported to allow backward compatibility with older versions of Java (like 1.0).
  • Since HashMap is not synchronized, it will be much faster in non-threaded scenarios than HashTable.

What is the difference between LinkedList and ArrayList?

  • Both ArrayList and LinkedList are implementations of the java.util.List interface. LinkedList implements java.util.Deque in addition to the List interface. Apart from the methods like add() and remove() which LinkedList shares with ArrayList, addFirst(), addLast(), removeFirst() and removeLast() methods are also present in LinkedList implementation
  • ArrayList is backed by arrays in underlying implementation. This is a way to realize dynamic arrays (that is, an array with no predetermined size and which grows according to the data added). The underlying implementation of LinkedList is a doubly ended LinkedList.
  • get(int index) method returns item at index in constant time in case of an ArrayList( as the underlying data structure is an Array). But it takes O(n) time in case of a LinkedList.
  • Insert(object) operation is faster in LinkedList than that of an ArrayList. This is because each time a new item is added to ArrayList, the underlying Array backing the list is discarded after copying the values to the newly created Array with size (oldarray + 1). This creation of new array and discarding old array is a time-consuming process. But in the case of LinkedList, you just need to traverse from head to the particular position and change the previous and next pointers of the list node at the position.
  • Memory utilization in case of LinkedList is more than that of an array list because of the extra memory required for denoting previous and next nodes of the particular node.

What is a comparator? How different is it from comparable?

Comparator and Comparable are used when it is required to sort a collection of user defined class or wrapper class’ collection.

Comparable

  • Implemented by wrapper classes and strings. If you are implementing a custom class, you may use:
public class MyCustomClass implements Comparable<MyCustomClass>{

	Double weight;
	
	public Double getWeight(){
		return this.weight;
	}
	
	public MyCustomClass(){}
	
	public MyCustomClass(Double weight){
		this.weight = weight;
	}

	// more members and member functions, //getter, constructors etc go here.
	@Override
	public int compareTo(MyCustomClass c) {
		return this.weight.compareTo(c.getWeight());
	}

}

  • Only one way to sort can be done.
  • As seen earlier, the class for which the comparison has to be made needs to be changed here.
  • Method used is public int compareTo(MyCustomClass c )

Comparator

  • Implemented by a new class that shall be used alongwith custom class’s collection while calling Collections.sort() or Arrays.sort()
  • Many comparators can be created to sort based on many criterions.
  • In this case, you build a separate class which can be used to sort the custom class object’s list.
  • Method used is int compare(MyCustomClass c1, MyCustomClass c2);

 

How would you search for a value in a collection or an array?

In the helper classes like java.util.Collections and java.util.Arrays, there is a function named binarySearch which does this for you. For a given element, Collections.binarySearch or Arrays.binarySearch will return the position of first occurrence of the element in the collection or array and returns -1 if it is not present in the collection/array.

How to get an array of items from a given List?

You can use Collections.toArray(list) to get the contents of the list in form of an array. Similarly, Arrays.asList(array) can be used to get the values of the array in list format.

What are concurrent collections?

Java 1.5 introduced java.util.concurrent package which contains thread-safe collections that do not throw ConcurrentModificationException while trying to modify during a traversal. Some of the significant classes in this package are CopyOnWriteArrayList, ConcurrentHashMap, ConcurrentLinkedDeque, ArrayBlockingQueue, etc.

What will be the output for the following code?

import java.util.*;

public class PriorityQueueTest {

	public static void main(String[] args) {
		PriorityQueue<String> pQueue = new PriorityQueue<String>();
		pQueue.add("Java");
		pQueue.add("Collections");
		pQueue.add(null);
		System.out.println(pQueue.size());
	}
}

The above code will compile properly but during runtime, it would throw a NullPointerException. This is because PriorityQueue does not allow null values to be added to it.

 

 

You may also be interested in:

Like this post? Don’t forget to share it!

5 Comments

  1. Javed

    Thanks. Here are more usecases for unmodifiableList.
    When a library is exposing a List to the outside world and is itself also using that List. The Library should give an unmodifiable List to the outside. This makes sure that the List for the library is not modified outside the Library. And it is also useful in the multithreaded environment and avoids CuncorrentModificationException.

    • T Tak

      Yes, you are absolutely right with these usecases.Thanks. Correction for Typo: ConcurrentModificationException

  2. Rajeshwari

    An interviewer should never ask questions about internal implementation of Java Classes. It is important to know how a class is used rather than how it works internally. I really would like to know what you think about that?

    • T Tak

      All the questions here are really about understanding the concepts of collections framework. It is good to know, how internal components work.

  3. Kalima

    Here are some questions that i have been preparing for my interviews.
    What is the difference between HashMap and ConcurrentHashMap ?
    How to defend aganist ConcurrentModificationException?
    How to handle collecions in multithreaded environments?

Leave a Reply

Your email address will not be published. Required fields are marked *