Collections Interview Questions
The Collections Framework is one of the most-tested topics in Java interviews at every level. Expect questions ranging from “what’s the difference between List and Set?” all the way to “walk me through how HashMap resolves hash collisions.” This page covers the questions that come up most often, with crisp answers and runnable code to cement your understanding.
Foundations
1. What is the Java Collections Framework?
The Java Collections Framework (JCF) is a unified architecture — interfaces, implementations, and utility algorithms — for storing and manipulating groups of objects. The root interfaces are:
| Interface | Ordered? | Duplicates? | Key implementations |
|---|---|---|---|
List | Yes (insertion) | Yes | ArrayList, LinkedList |
Set | No guarantee | No | HashSet, LinkedHashSet, TreeSet |
Queue | Yes (FIFO/priority) | Yes | LinkedList, PriorityQueue |
Deque | Both ends | Yes | ArrayDeque, LinkedList |
Map | No guarantee | Keys: No | HashMap, LinkedHashMap, TreeMap |
Note:
Mapdoes not extendCollection, but it is still considered part of the framework.
2. What is the difference between Collection and Collections?
Collection(lowercase c at the end) is the root interface thatList,Set, andQueueextend.Collectionsis a utility class (likeArrays) that provides static helper methods:sort(),shuffle(),unmodifiableList(),synchronizedList(), etc.
3. What is the difference between ArrayList and LinkedList?
Both implement List, but they have very different internal structures.
import java.util.*;
List<String> arrayList = new ArrayList<>(); // backed by Object[]
List<String> linkedList = new LinkedList<>(); // doubly-linked nodes
| Operation | ArrayList | LinkedList |
|---|---|---|
Random access (get(i)) | O(1) | O(n) |
| Add/remove at end | O(1) amortised | O(1) |
| Add/remove in middle | O(n) — shifts elements | O(1) — re-links nodes |
| Memory | Compact (array) | More — each node stores two pointers |
Tip: In practice,
ArrayListwins for most use cases because CPU caches love contiguous memory. PreferLinkedListonly when you do frequent insertions/removals at both ends (and even then,ArrayDequeis usually faster).
See ArrayList and LinkedList for deeper dives, and ArrayList vs LinkedList for a direct comparison.
HashMap Deep Dive
These questions come up in almost every mid-to-senior interview.
4. How does HashMap work internally?
A HashMap stores entries in an array of buckets. The index for a key is computed as:
bucket index = (n - 1) & hash(key)
where n is the current capacity (default 16). Multiple keys can hash to the same bucket — this is a collision. Java resolves collisions using a linked list within the bucket; from Java 8 onwards, that list is converted to a balanced red-black tree when a bucket exceeds 8 entries (and back to a list if it shrinks below 6).
import java.util.*;
Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 95);
scores.put("Bob", 87);
scores.put("Carol", 92);
// Internally: hash("Alice") -> bucket X -> Node{key, value, next}
System.out.println(scores.get("Alice")); // 95
Output:
95
For a complete walkthrough, see Working of HashMap.
5. What is the load factor and rehashing?
The load factor (default 0.75) is the ratio size / capacity at which HashMap doubles its capacity and rehashes all entries. A lower load factor means fewer collisions but more memory; a higher load factor saves memory but increases collision probability.
// Custom initial capacity and load factor
Map<String, Integer> map = new HashMap<>(32, 0.5f);
6. What happens if two keys have the same hashCode()?
They land in the same bucket — a collision. Java walks the bucket’s list (or tree) comparing keys with equals(). This is why the contract “if a.equals(b), then a.hashCode() == b.hashCode()” is critical: violating it causes HashMap to silently lose entries.
public class BadKey {
int id;
BadKey(int id) { this.id = id; }
@Override
public boolean equals(Object o) {
return o instanceof BadKey bk && bk.id == this.id;
}
// hashCode() NOT overridden — BROKEN: equals but different hashes
}
Warning: Always override
hashCode()whenever you overrideequals(). Failing to do so breaksHashMap,HashSet, and any hash-based collection.
7. What is the difference between HashMap and Hashtable?
| Feature | HashMap | Hashtable |
|---|---|---|
| Thread-safe? | No | Yes (every method synchronized) |
| Null keys/values | One null key, many null values | Neither |
| Performance | Faster (no sync overhead) | Slower |
| Legacy? | No — prefer this | Yes — avoid; use ConcurrentHashMap |
See HashMap vs Hashtable for more detail.
8. What is ConcurrentHashMap and how is it different from synchronizedMap?
Collections.synchronizedMap(map) wraps an entire map with a single mutex — every operation locks the whole map.
ConcurrentHashMap (from java.util.concurrent) uses segment-level locking (Java 7) or CAS + fine-grained bucket locking (Java 8+), allowing multiple threads to read and write different buckets concurrently without blocking each other.
import java.util.concurrent.*;
Map<String, Integer> safe = new ConcurrentHashMap<>();
safe.put("x", 1); // thread-safe, no global lock
See Concurrent Collections for the full picture.
List, Set, and Queue
9. What is the difference between HashSet, LinkedHashSet, and TreeSet?
| Class | Order | Null? | Performance |
|---|---|---|---|
HashSet | No order | One null | O(1) add/contains |
LinkedHashSet | Insertion order | One null | O(1) add/contains |
TreeSet | Sorted (natural or Comparator) | No | O(log n) add/contains |
Set<String> hash = new HashSet<>(List.of("B", "A", "C"));
Set<String> linked = new LinkedHashSet<>(List.of("B", "A", "C"));
Set<String> tree = new TreeSet<>(List.of("B", "A", "C"));
System.out.println(hash); // unpredictable order
System.out.println(linked); // [B, A, C]
System.out.println(tree); // [A, B, C]
Output:
[A, B, C] (hash — may vary)
[B, A, C]
[A, B, C]
10. How does PriorityQueue order its elements?
PriorityQueue is a min-heap by default — poll() always removes the smallest element according to natural ordering or a provided Comparator.
import java.util.*;
Queue<Integer> pq = new PriorityQueue<>();
pq.addAll(List.of(5, 1, 3));
System.out.println(pq.poll()); // 1
System.out.println(pq.poll()); // 3
Output:
1
3
Iterating Collections
11. What are the ways to iterate a List? What is fail-fast behavior?
List<String> list = new ArrayList<>(List.of("A", "B", "C"));
// 1. for-each (uses Iterator internally)
for (String s : list) System.out.println(s);
// 2. Iterator explicitly
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if (s.equals("B")) it.remove(); // safe removal during iteration
}
// 3. ListIterator (bidirectional)
ListIterator<String> lit = list.listIterator(list.size());
while (lit.hasPrevious()) System.out.println(lit.previous());
A fail-fast iterator throws ConcurrentModificationException if the collection is structurally modified (add/remove) while iterating — without going through the iterator itself. This is detected via an internal modCount counter.
Tip: Use
it.remove()(notlist.remove()) during iteration to avoidConcurrentModificationException.
12. What is the difference between Iterator and ListIterator?
| Feature | Iterator | ListIterator |
|---|---|---|
| Direction | Forward only | Forward and backward |
| Available for | Any Collection | List only |
| Can add elements? | No | Yes (add()) |
| Can replace element? | No | Yes (set()) |
See Iterator for more detail.
Sorting and Ordering
13. What is the difference between Comparable and Comparator?
Comparable(java.lang) defines the natural ordering of a class viacompareTo(). The class itself implements it.Comparator(java.util) defines an external ordering. You can have many comparators for the same class.
// Comparable: natural order by name
record Employee(String name, int salary) implements Comparable<Employee> {
@Override
public int compareTo(Employee o) {
return this.name.compareTo(o.name);
}
}
// Comparator: external order by salary
Comparator<Employee> bySalary = Comparator.comparingInt(Employee::salary);
List<Employee> employees = new ArrayList<>(List.of(
new Employee("Carol", 90000),
new Employee("Alice", 75000),
new Employee("Bob", 82000)
));
Collections.sort(employees); // natural: by name
employees.sort(bySalary); // by salary
employees.sort(bySalary.reversed()); // by salary desc
See Comparable, Comparator, and Comparable vs Comparator.
Maps and Special Types
14. What is TreeMap and when would you use it?
TreeMap stores entries sorted by key (natural order or a Comparator). It provides O(log n) operations and unique navigation methods:
import java.util.*;
TreeMap<Integer, String> map = new TreeMap<>();
map.put(3, "C"); map.put(1, "A"); map.put(2, "B");
System.out.println(map.firstKey()); // 1
System.out.println(map.headMap(3)); // {1=A, 2=B}
System.out.println(map.floorKey(2)); // 2
Output:
1
{1=A, 2=B}
2
Use TreeMap when you need sorted keys or range queries. For insertion-order iteration, use LinkedHashMap.
15. What is the difference between HashMap and TreeMap?
| Feature | HashMap | TreeMap |
|---|---|---|
| Order | No order | Sorted by key |
| Performance | O(1) average | O(log n) |
| Null key | Allowed | Not allowed |
| Use case | General-purpose | Range queries, sorted output |
Under the Hood
Java 8 HashMap Treeification
Before Java 8, a degenerate hash function could cause all keys to fall into the same bucket, turning O(1) lookups into O(n) linked-list scans. Java 8 introduced treeification: when a single bucket exceeds TREEIFY_THRESHOLD (8 nodes), it converts that chain into a red-black tree, capping worst-case lookup at O(log n) even under adversarial hashing.
ArrayList Internal Growth
An ArrayList starts with a backing array of capacity 10 (or the size you specify). When it fills up, a new array of size (oldCapacity * 3) / 2 + 1 (roughly 1.5×) is allocated and all elements are copied via Arrays.copyOf(). If you know the final size upfront, pass it to the constructor to avoid repeated allocations:
List<Integer> list = new ArrayList<>(10_000); // no resizing needed
EnumSet and EnumMap
For enum-keyed collections, prefer EnumSet and EnumMap. They are backed by bit-vectors and arrays respectively — dramatically faster and more memory-efficient than HashSet/HashMap for enums.
Quick-Reference Cheat Sheet
| Question | Short Answer |
|---|---|
ArrayList vs LinkedList? | Array → fast random access; Linked → fast mid-inserts |
Null in HashMap? | One null key, many null values |
Null in Hashtable? | Neither |
TreeSet ordering? | Sorted; no null |
HashSet ordering? | No guarantee |
| Thread-safe Map? | ConcurrentHashMap |
| Remove during iteration? | Use iterator.remove() |
| Natural ordering interface? | Comparable (compareTo) |
| External ordering interface? | Comparator (compare) |
| HashMap collision fix (Java 8)? | Treeify bucket to red-black tree |
Related Topics
- Working of HashMap (Internals) — understand exactly how
put()andget()work under the hood - Comparable vs Comparator — when to use each sorting strategy
- Concurrent Collections — thread-safe alternatives for multi-threaded code
- ArrayList vs LinkedList — performance trade-offs explained with benchmarks
- Collections Utility Class — sorting, searching, and wrapping collections
- Concurrency Interview Questions — the next most-tested topic after collections