Collections Framework Interview Questions for Java
25 Collections Framework questions with answers for java roles — 10 easy, 12 medium, 3 hard.
About Collections Framework
The Collections Framework is the most asked area in Java interviews. Understand List, Set, Queue, Deque and Map implementations, internal working of HashMap and HashSet, Comparable and Comparator, fail-fast iterators, immutable collections and how to pick the right structure for performance, with common DSA problems solved using collections.
Sheet progressStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
✓ 3 questions free • Unlock the rest in seconds
01
Explain the hierarchy of the Java Collections Framework.
The root interface is Iterable, then Collection, which has List (ordered, allows duplicates: ArrayList, LinkedList), Set (unique: HashSet, LinkedHashSet, TreeSet) and Queue/Deque (PriorityQueue, ArrayDeque). Map is separate and stores key-value pairs: HashMap, LinkedHashMap, TreeMap and ConcurrentHashMap. Java 21 added SequencedCollection and SequencedMap with getFirst() and getLast().
02
What is the difference between ArrayList and LinkedList?
ArrayList is backed by a resizable array, so get(i) is O(1) and appends are amortised O(1), but inserting in the middle shifts elements. LinkedList is a doubly linked list with O(n) random access but O(1) add or remove at the ends or through an iterator. In practice ArrayList is faster for almost all cases because of better CPU cache use; use ArrayDeque for queues.
03
What is the difference between HashMap, LinkedHashMap and TreeMap?
HashMap gives O(1) average operations with no ordering guarantee. LinkedHashMap keeps insertion order, or access order if configured, which helps build an LRU cache. TreeMap keeps keys sorted by natural order or a Comparator with O(log n) operations and supports range methods like floorKey and headMap. HashMap allows one null key; TreeMap does not allow null keys with natural ordering.
04
What is the difference between Comparable and Comparator?
Comparable defines a class's natural ordering through compareTo() inside the class, such as String sorted alphabetically. Comparator is a separate object with compare(), so you can define many orderings without changing the class. Java 8 made Comparator easy: Comparator.comparing(Employee::getSalary).reversed().thenComparing(Employee::getName). TreeMap and sort methods accept either.
HashSet is backed by a HashMap. Each element you add becomes a key in that map with a shared dummy object as the value. So uniqueness depends entirely on the element's hashCode() and equals(), and operations are O(1) on average. LinkedHashSet uses a LinkedHashMap to keep insertion order, and TreeSet uses a TreeMap to keep elements sorted.
06
You need to remove items from an ArrayList while looping over it. How do you do it safely?
Removing inside a for-each loop throws ConcurrentModificationException. Use list.removeIf(item -> item.isExpired()), which is clear and efficient. Alternatives are an explicit Iterator calling iterator.remove(), or looping backwards by index. For large lists removeIf is best because it shifts elements once instead of on every removal.
07
Sort a list of employees by department, then by salary descending.
Chain comparators.
employees.sort(
Comparator.comparing(Employee::department)
.thenComparing(Employee::salary,
Comparator.reverseOrder()));
// Streams version returning a new list
List<Employee> sorted = employees.stream()
.sorted(Comparator.comparing(Employee::department)
.thenComparing(Employee::salary, Comparator.reverseOrder()))
.toList();
List.sort is stable, so equal keys keep their order.
08
Write a Java solution for the Two Sum problem using a HashMap.
Store each number's index and look up its complement.
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> seen = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
Integer j = seen.get(target - nums[i]);
if (j != null) return new int[]{j, i};
seen.put(nums[i], i);
}
return new int[0];
}
One pass, O(n) time and O(n) space.
09
Remove duplicates from a list while keeping the original order.
A LinkedHashSet keeps first-seen order.
List<String> unique = new ArrayList<>(new LinkedHashSet<>(names));
// or with streams
List<String> unique2 = names.stream()
.distinct()
.toList();
Both rely on equals() and hashCode(), and both run in O(n) on average.
10
How do you prepare for coding rounds as a Java developer?
Situation: I was preparing for product company interviews while working. Task: get strong at DSA in limited time. Action: I solved two problems a day by pattern, such as sliding window and graphs, always in Java with Collections, timed myself and reviewed mistakes every weekend. Result: in three months I solved 250 problems, cleared online tests comfortably and could explain time complexity clearly.
HashMap stores entries in an array of buckets. It computes the key's hashCode(), spreads the bits and picks a bucket index. Collisions are stored as a linked list in the bucket, and since Java 8 a bucket with more than 8 entries (when the table has at least 64 buckets) becomes a red-black tree, making the worst case O(log n). When size passes capacity times load factor 0.75, it resizes to double.
12
What is the difference between HashMap and ConcurrentHashMap?
HashMap is not thread safe; concurrent writes can lose data or corrupt the structure. ConcurrentHashMap supports full concurrency: reads are lock free and writes use CAS or lock a single bin, so threads rarely block each other. It does not allow null keys or values. It also provides atomic compound operations such as computeIfAbsent and merge, which avoid check-then-act races.
Fail-fast iterators, used by ArrayList and HashMap, throw ConcurrentModificationException if the collection is structurally modified during iteration other than through the iterator itself; they check a modCount. Fail-safe or weakly consistent iterators, as in ConcurrentHashMap and CopyOnWriteArrayList, work on a snapshot or tolerate changes and never throw, but may not show the latest updates.
14
What is the difference between List.of(), Arrays.asList() and Collections.unmodifiableList()?
List.of() returns a truly immutable list; add, set and remove throw exceptions and nulls are not allowed. Arrays.asList() returns a fixed-size list backed by the array: set() works and writes through to the array, but add() and remove() throw. Collections.unmodifiableList() is a read-only view, so changes to the original list are still visible through it.
15
You need a cache that evicts the least recently used item when full. How would you build it in Java?
Extend LinkedHashMap with accessOrder set to true and override removeEldestEntry to return true when size exceeds capacity. Each get moves the entry to the end, so the eldest is the least recently used. It is not thread safe, so wrap it with synchronization for shared use. In production prefer Caffeine, which offers size and time based eviction with high concurrency.
16
A HashMap shared by many threads sometimes loses updates. How do you fix it?
HashMap is not thread safe, so concurrent put calls can overwrite each other. Replace it with ConcurrentHashMap and use atomic methods instead of get-then-put, for example counts.merge(key, 1, Integer::sum) or computeIfAbsent for lazy creation. Collections.synchronizedMap also works but locks the whole map, which hurts throughput under contention.
17
You have to process tasks in order of priority. Which collection do you use?
Use PriorityQueue, a binary heap where poll() always returns the smallest element by natural order or by a Comparator, such as Comparator.comparingInt(Task::priority). Insert and poll are O(log n) and peek is O(1). For multiple threads use PriorityBlockingQueue. Iterating a PriorityQueue does not give sorted order; only repeated poll() does.
18
An API needs to find the price band for any amount, for example the nearest lower slab. Which structure fits?
TreeMap is ideal because it keeps keys sorted and offers navigation methods. Store slab start amounts as keys and the band as value, then floorEntry(amount) returns the largest slab not above the amount in O(log n). ceilingKey, headMap and tailMap help with similar range queries such as tax slabs or delivery charges.
Access order plus removeEldestEntry gives LRU in a few lines.
class LruCache<K, V> extends LinkedHashMap<K, V> {
private final int capacity;
LruCache(int capacity) {
super(16, 0.75f, true);
this.capacity = capacity;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> e) {
return size() > capacity;
}
}
get and put are O(1).
20
Group a list of orders by city and sum the amount per city.
Use groupingBy with a summing collector.
Map<String, Double> totals = orders.stream()
.collect(Collectors.groupingBy(
Order::city,
TreeMap::new,
Collectors.summingDouble(Order::amount)));
TreeMap keeps cities sorted. For money, store amounts as long paise or BigDecimal and use Collectors.reducing with BigDecimal::add.
21
When would you choose ArrayDeque over Stack and LinkedList?
Stack is a legacy synchronized class built on Vector, so it is slow and exposes index methods that break stack rules. LinkedList allocates a node per element. ArrayDeque is a resizable circular array with no per-element allocation, so push, pop, offer and poll are fast amortised O(1). Use ArrayDeque for both stacks and queues in single-threaded code; it does not accept null.
22
Tell me about a time you improved performance by choosing a better data structure.
Situation: a report job matching 2 lakh transactions to customers took 40 minutes. Task: bring it under the 5 minute window. Action: profiling showed list.contains() inside a loop, which was O(n squared). I loaded customer ids into a HashSet and grouped transactions with a HashMap. Result: runtime dropped to 50 seconds and I shared the pattern in our team wiki.
23
Why must you be careful when initial capacity of a HashMap is too small?
If a HashMap starts small and grows large, it resizes many times; each resize allocates a new array and rehashes every entry, which costs CPU and creates garbage. When the expected size is known, use HashMap.newHashMap(n) in Java 19 or later, or set capacity to n divided by 0.75. Too large a capacity wastes memory, so size it to real data.
24
Memory usage is high because millions of Integer objects are stored in an ArrayList. What would you do?
Each Integer is a separate object with header overhead and a reference, so a List of Integer uses several times more memory than the raw data. If size is known, use an int[] array. Otherwise use primitive collections from libraries such as Eclipse Collections or fastutil, which store ints directly. This also improves cache performance and reduces GC pressure.
Count with a map, then keep a min-heap of size K.
Map<String, Integer> cnt = new HashMap<>();
for (String w : words) cnt.merge(w, 1, Integer::sum);
PriorityQueue<String> pq = new PriorityQueue<>(
Comparator.comparingInt(cnt::get));
for (String w : cnt.keySet()) {
pq.offer(w);
if (pq.size() > k) pq.poll();
}
Time O(n log k). Reverse the heap contents for highest first.
Frequently asked questions
How important is Collections Framework in Java interviews?
The Collections Framework is the most asked area in Java interviews. Understand List, Set, Queue, Deque and Map implementations, internal working of HashMap and HashSet, Comparable and Comparator, fail-fast iterators, immutable collections and how to pick the right structure for performance, with common DSA problems solved using collections.
How should I use the Collections Framework sheet?
Go top to bottom — easy to hard. Answer before opening each answer, tick what you solved and save misses to Last-Minute Revision.