Practice commonly asked
Collections interview questions with clear answers and explanations.
30
Interview Questions
Questions & Answers
Collections Interview Questions
30 Questions
Q 31
How does spliterator() work and how does it differ from iterator()?
Hard
Answer
Spliterator (Splitting Iterator) is designed for parallel processing of elements. Unlike Iterator which traverses sequentially, Spliterator can partition elements into sub-spliterators via trySplit() for multi-threaded processing.
Explanation
Spliterators report characteristics (ORDERED, DISTINCT, SORTED, SIZED, etc.) that enable Stream execution engines to optimize pipeline evaluation.
Code Example
Java
List<String> list = List.of("A", "B", "C", "D");
Spliterator<String> split1 = list.spliterator();
Spliterator<String> split2 = split1.trySplit(); // Splits half elements into split2
split1.forEachRemaining(System.out::println); // Processes remainder
split2.forEachRemaining(System.out::println); // Processes first partition
Reference:
Java Collections Framework
Q 32
What is the difference between Collection.stream().forEach() and Collection.forEach()?
Medium
Answer
Collection.forEach() uses the collection's Iterator or Spliterator directly. Collection.stream().forEach() processes elements via the Stream pipeline, which introduces overhead unless stream operations (filter, map) or parallel streams are needed.
Explanation
Collection.forEach() preserves structural traversal semantics, while stream().forEach() in parallel streams does not guarantee ordering unless forEachOrdered() is used.
SynchronousQueue is a blocking queue with zero internal capacity. Each insert operation (put) must wait for a corresponding take operation by another thread, facilitating direct handoff.
Explanation
SynchronousQueue is used in Executors.newCachedThreadPool() where worker threads take tasks directly from submitter threads without queuing.
Code Example
Java
BlockingQueue<String> syncQueue = new SynchronousQueue<>();
// Producer thread will block on put() until Consumer thread calls take()
new Thread(() -> {
try { syncQueue.put("Data Handoff"); } catch (InterruptedException e) {}
}).start();
Reference:
Java Collections Framework
Q 34
What is DelayQueue and how does it function in Java?
Hard
Answer
DelayQueue is an unbounded blocking queue of Delayed elements. An element can only be taken from the queue when its delay time has expired.
Explanation
DelayQueue keeps elements ordered by delay expiration time (head has the oldest expired delay). It is widely used in task scheduling, session expiration, and retry mechanisms.
Code Example
Java
public class DelayedTask implements Delayed {
private final long executeTime;
public DelayedTask(long delayInMs) {
this.executeTime = System.currentTimeMillis() + delayInMs;
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(executeTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
return Long.compare(this.executeTime, ((DelayedTask) o).executeTime);
}
}
Reference:
Java Collections Framework
Q 35
What is the difference between Queue poll(), remove(), peek(), and element() methods?
Easy
Answer
poll() and remove() retrieve and remove the head of the queue; poll() returns null if empty while remove() throws NoSuchElementException. peek() and element() inspect the head without removing; peek() returns null if empty while element() throws an exception.
Explanation
Use poll() and peek() when an empty queue is a normal conditional occurrence. Use remove() and element() when an empty queue indicates an unexpected application state.
How does Arrays.asList() differ from List.of() and new ArrayList<>()?
Medium
Answer
Arrays.asList() returns a fixed-size wrapper backed by the original array (allows set, disallows add/remove, allows nulls). List.of() returns an unmodifiable list (disallows all mutations, disallows nulls). new ArrayList<>() creates a fully mutable dynamic list.
Explanation
Modifications via set() on Arrays.asList() mutate the backing array directly. List.of() throws UnsupportedOperationException on set/add/remove and NPE on nulls.
NavigableMap and NavigableSet extend SortedMap and SortedSet to provide navigation methods like lower(), floor(), ceiling(), higher(), and descendingMap()/descendingSet().
Explanation
TreeMap implements NavigableMap, and TreeSet implements NavigableSet. These interfaces allow efficient closest-match range searching in O(log n) time.
What is LinkedHashMap and how does it implement LRU (Least Recently Used) caching?
Hard
Answer
LinkedHashMap extends HashMap by maintaining a doubly-linked list across entries. When constructed with accessOrder=true, it maintains access order, and overriding removeEldestEntry allows simple LRU cache creation.
Explanation
Setting accessOrder=true reorders elements whenever get() or put() is called, placing accessed elements at the tail. The eldest entry at the head can be evicted automatically.
Code Example
Java
public class LruCache<K, V> extends LinkedHashMap<K, V> {
private final int maxCapacity;
public LruCache(int maxCapacity) {
super(maxCapacity, 0.75f, true); // accessOrder = true
this.maxCapacity = maxCapacity;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maxCapacity; // Evicts LRU entry
}
}
Reference:
Java Collections Framework
Q 39
What is the initial default capacity and load factor of HashMap, and how is the capacity resized?
Medium
Answer
The initial default capacity of HashMap is 16 and the default load factor is 0.75. When the number of entries exceeds capacity * load factor, the capacity doubles (power of 2) and rehashing occurs.
Explanation
HashMap capacity is always forced to a power of two so that bitwise AND operations (hash & (capacity - 1)) can be used instead of slow modulo (%) operations to find bucket indices.
Code Example
Java
// Custom initial capacity and load factor
Map<String, String> map = new HashMap<>(32, 0.8f);
// Threshold for resizing = 32 * 0.8 = 25 entries
map.put("Key", "Value");
Reference:
Java Collections Framework
Q 40
How do you choose the right Collection implementation in Java?
Medium
Answer
Choose based on requirements: duplicates allowed (List), unique elements (Set), key-value mapping (Map), ordering (SortedSet/TreeSet), FIFO/LIFO processing (Queue/Deque), and concurrency needs.
Explanation
Always default to ArrayList for dynamic arrays, HashSet for lookup sets, HashMap for key-value stores, and switch to concurrent implementations (ConcurrentHashMap) when multi-threading.
Code Example
Java
// Quick decision rule:
// Need key-value + Fast lookup -> HashMap
// Need Unique + Fast lookup -> HashSet
// Need Ordered sequence + Indexed access -> ArrayList
// Need FIFO queue -> ArrayDeque / LinkedList
Reference:
Java Collections Framework
Q 41
What is the utility of the Collections class in Java?
Easy
Answer
Collections is a utility class consisting exclusively of static methods that operate on or return collections (such as sort, binarySearch, reverse, synchronizedList, unmodifiableMap).
Explanation
Do not confuse Collection (the core interface) with Collections (the static utility class).
Code Example
Java
List<Integer> numbers = new ArrayList<>(List.of(5, 2, 8, 1));
Collections.sort(numbers);
Collections.reverse(numbers);
int index = Collections.binarySearch(numbers, 5);
Reference:
Java Collections Framework
Q 42
What is BlockingQueue and where is it used in Java?
Hard
Answer
BlockingQueue is a thread-safe Queue that blocks the producer thread when trying to insert into a full queue, and blocks the consumer thread when trying to retrieve from an empty queue.
Explanation
BlockingQueue implementations (e.g. ArrayBlockingQueue, LinkedBlockingQueue) are fundamental building blocks for Producer-Consumer patterns and ExecutorService thread pools.
Code Example
Java
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
// Producer thread
queue.put("Task"); // Blocks if full
// Consumer thread
String task = queue.take(); // Blocks if empty
Reference:
Java Collections Framework
Q 43
What is subList() in List and what is its side effect?
Medium
Answer
subList(fromIndex, toIndex) returns a sub-range view backed by the original list. Changes made to the subList reflect directly in the parent list and vice-versa.
Explanation
Structural changes (adding/removing elements) made directly to the backing list invalidate the subList view and cause subsequent subList calls to throw ConcurrentModificationException.
Code Example
Java
List<String> parent = new ArrayList<>(List.of("A", "B", "C", "D"));
List<String> sub = parent.subList(1, 3); // View containing ["B", "C"]
sub.clear(); // Removes "B" and "C" from parent list!
System.out.println(parent); // Prints ["A", "D"]
Reference:
Java Collections Framework
Q 44
What is WeakHashMap and how does Garbage Collection interact with it?
Hard
Answer
WeakHashMap stores key references as WeakReference instances. When a key is no longer strongly referenced elsewhere, GC reclaims the key and the entry is automatically purged from the map.
Explanation
WeakHashMap is commonly used for constructing memory-sensitive caches or maintaining metadata for active objects.
Code Example
Java
Map<Object, String> map = new WeakHashMap<>();
Object key = new Object();
map.put(key, "Cache Data");
key = null; // Key becomes eligible for GC
System.gc(); // Triggers garbage collection
// Entry will automatically disappear from WeakHashMap
Reference:
Java Collections Framework
Q 45
What is EnumSet and why is it preferred for Enums?
Medium
Answer
EnumSet is a highly optimized Set implementation for enum types backed by bit vectors (long fields). It provides superior performance and memory efficiency compared to HashSet.
Explanation
EnumSet operations execute in constant O(1) time utilizing fast bitwise CPU operations.
What is identity HashMap and how does it differ from standard HashMap?
Hard
Answer
IdentityHashMap uses reference equality (==) instead of logical equality (equals()) when comparing keys and values, and uses System.identityHashCode() for hash computation.
Explanation
IdentityHashMap is useful during graph serialization or deep cloning object trees to track distinct object instances regardless of value equality.
Code Example
Java
Map<String, String> map = new IdentityHashMap<>();
String key1 = new String("key");
String key2 = new String("key");
map.put(key1, "Val1");
map.put(key2, "Val2");
System.out.println(map.size()); // Prints 2 because key1 != key2 by reference
Reference:
Java Collections Framework
Q 47
What are unmodifiable collections and how are they created in modern Java?
Easy
Answer
Unmodifiable collections throw UnsupportedOperationException if any modification attempt is made. They are created using List.of(), Set.of(), Map.of() (Java 9+) or Collections.unmodifiableList().
Explanation
List.of() creates truly immutable and null-disallowing collection implementations, whereas Collections.unmodifiableList() creates an unmodifiable wrapper view around an underlying mutable list.
What is the difference between ArrayDeque and Stack?
Medium
Answer
Stack is a legacy class extending Vector that synchronizes all operations. ArrayDeque implements the Deque interface, is unsynchronized, faster, and recommended over Stack for LIFO queue implementations.
Explanation
ArrayDeque uses a resizable array circular buffer. It does not suffer from synchronization locking overhead like legacy Stack.
PriorityQueue is an unbounded queue whose elements are ordered according to natural priority or an explicit Comparator. It is implemented internally as a priority heap array.
Explanation
PriorityQueue offers O(log n) time for enqueuing and dequeuing operations (offer/poll). It does not permit null elements.
Code Example
Java
// Min-heap by default
Queue<Integer> pq = new PriorityQueue<>();
pq.offer(30);
pq.offer(10);
pq.offer(20);
System.out.println(pq.poll()); // Prints 10 (smallest element first)
Reference:
Java Collections Framework
Q 50
What is the difference between Fail-Fast and Fail-Safe iterators?
Medium
Answer
Fail-Fast iterators throw ConcurrentModificationException immediately if a collection is structurally modified during iteration. Fail-Safe iterators iterate over a copy or snapshot and do not throw exceptions when underlying collections change.
Explanation
ArrayList, HashSet, and HashMap use fail-fast iterators (tracked via modCount). ConcurrentHashMap and CopyOnWriteArrayList use weakly consistent or fail-safe iterators.
Code Example
Java
List<String> list = new ArrayList<>(List.of("A", "B"));
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String val = it.next();
// list.add("C"); // Throws ConcurrentModificationException
it.remove(); // Valid safe removal via Iterator
}
Reference:
Java Collections Framework
Q 51
How does CopyOnWriteArrayList achieve thread safety?
Medium
Answer
CopyOnWriteArrayList creates a fresh underlying array clone every time a mutating operation (add, set, remove) occurs, ensuring iterators operate safely on immutable snapshot arrays.
Explanation
CopyOnWriteArrayList is ideal for read-heavy scenarios with very few mutations, as array copy overhead during writes is high.
Code Example
Java
List<String> safeList = new CopyOnWriteArrayList<>();
safeList.add("Alpha");
// Iteration never throws ConcurrentModificationException even if modified concurrently
for (String s : safeList) {
safeList.add("Beta"); // Modifies underlying array snapshot copy
}
Reference:
Java Collections Framework
Q 52
What is the difference between Synchronized Collections and Concurrent Collections?
Medium
Answer
Synchronized wrapper collections (Collections.synchronizedList) lock the entire collection object for every method call. Concurrent collections (CopyOnWriteArrayList, ConcurrentHashMap) use lock-free or fine-grained lock mechanisms for high performance under concurrent loads.
Explanation
Synchronized wrappers can still throw ConcurrentModificationException during explicit thread iteration unless manually synchronized on the wrapper instance.
What is ConcurrentHashMap and how does it achieve thread safety?
Hard
Answer
ConcurrentHashMap is a thread-safe map that uses bucket-level fine-grained lock striping (CAS operations and synchronized blocks on individual head nodes) instead of locking the entire table like Hashtable.
Explanation
ConcurrentHashMap never blocks read operations and allows concurrent multi-threaded writes without throwing ConcurrentModificationException.
What is the difference between Comparable and Comparator in Java?
Easy
Answer
Comparable provides a class with a natural sorting sequence via compareTo(T o). Comparator is a functional interface allowing multiple custom sorting algorithms externally via compare(T o1, T o2).
Explanation
Implement Comparable inside domain entities for default ordering. Pass custom Comparator lambdas to sorting methods when alternative ordering logic is needed.
Code Example
Java
List<User> users = getUsers();
// Natural order defined inside User implementing Comparable
Collections.sort(users);
// Custom order using Comparator lambda
users.sort(Comparator.comparing(User::getAge).reversed());
Reference:
Java Collections Framework
Q 55
What is the difference between HashSet, LinkedHashSet, and TreeSet?
Medium
Answer
HashSet offers unordered element storage with O(1) performance. LinkedHashSet maintains insertion order via a doubly-linked list. TreeSet maintains sorted natural order (or custom Comparator) using a Red-Black tree with O(log n) performance.
Explanation
Use HashSet for performance when order does not matter, LinkedHashSet when insertion ordering is required, and TreeSet when elements must remain continuously sorted.
Code Example
Java
Set<String> hashSet = new HashSet<>(List.of("C", "A", "B")); // Order unpredictable
Set<String> linkedHashSet = new LinkedHashSet<>(List.of("C", "A", "B")); // Keeps "C", "A", "B"
Set<String> treeSet = new TreeSet<>(List.of("C", "A", "B")); // Automatically sorted: "A", "B", "C"
Reference:
Java Collections Framework
Q 56
Why must equals() and hashCode() contracts be strictly obeyed in Map keys?
Medium
Answer
If two objects are equal according to equals(), they MUST return the exact same hashCode(). Violating this contract breaks key lookup in hash-based collections like HashMap and HashSet.
Explanation
If equal objects produce different hash codes, HashMap will route them to different bucket locations during put() and get(), resulting in missed lookups and duplicate keys.
Code Example
Java
public class Employee {
private int id;
private String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Employee e)) return false;
return id == e.id && Objects.equals(name, e.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
Reference:
Java Collections Framework
Q 57
How does HashMap work internally in Java?
Hard
Answer
HashMap uses an array of buckets storing key-value pairs. Keys are hashed via hashCode() to determine bucket index. Collisions are handled using linked lists, which convert to balanced Red-Black Trees (TREEIFY_THRESHOLD = 8) when bucket size exceeds 8.
Explanation
Treeification improves collision lookup worst-case performance from O(n) in linked lists to O(log n) in balanced red-black trees. When the map resizes, capacity doubles when size exceeds capacity * load factor (default 0.75).
Code Example
Java
Map<String, Integer> scores = new HashMap<>();
// Internally calls String.hashCode(), calculates bucket index
scores.put("Alice", 95);
scores.put("Bob", 88);
int score = scores.get("Alice"); // O(1) average lookup
Reference:
Java Collections Framework
Q 58
What is the difference between ArrayList and LinkedList in Java?
Easy
Answer
ArrayList is backed by a dynamically resizing array providing O(1) random access, whereas LinkedList is implemented as a doubly-linked list providing fast O(1) element insertions/deletions at ends but O(n) positional access.
Explanation
ArrayList is generally preferred for reading and iterating data because of superior CPU cache locality, while LinkedList is suitable for frequent insertions and removals at arbitrary ends.
Code Example
Java
List<String> arrayList = new ArrayList<>();
arrayList.add("Item 1"); // Fast append, O(1) indexed get
List<String> linkedList = new LinkedList<>();
linkedList.add("Item 1"); // Fast head/tail operations
Reference:
Java Collections Framework
Q 59
What is the Java Collections Framework and what are its core interfaces?
Easy
Answer
The Java Collections Framework (JCF) is an architecture for representing and manipulating collections of objects. Core interfaces include Collection, List, Set, Queue, Deque, and Map.
Explanation
Note that Map is part of the Java Collections Framework but does not extend the root Collection interface because it manages key-value pairs rather than individual elements.
Code Example
Java
Collection<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
Map<String, Integer> map = new HashMap<>();
list.add("Java");
set.add("Java");
map.put("Java", 17);
Reference:
Java Collections Framework
Q 60
Why should Vector and Stack classes be avoided in modern Java applications?
Easy
Answer
Vector and Stack are legacy classes from Java 1.0 that synchronize every method individually, introducing heavy lock performance overhead. They are replaced by ArrayList, ArrayDeque, and modern concurrency classes.
Explanation
Stack extends Vector, which violates the LIFO abstraction by exposing vector index operations (e.g. stack.add(index, element)). Use ArrayDeque instead.
Code Example
Java
// Legacy approach:
Stack<String> legacyStack = new Stack<>();
// Modern approach:
Deque<String> modernStack = new ArrayDeque<>();
Reference:
Java Collections Framework
About This Topic
Prepare for
Collections interviews with important concepts
and commonly asked questions.