The Java Collections Framework is one of the most important parts of Java programming. It provides powerful data structures and algorithms to store and manipulate data efficiently. Technical interviews often include Java collections interview questions, so mastering them is essential. This article covers both basic Java collections interview questions and advanced Java collections interview questions with clear answers, examples, and explanations.
Table of Contents
Basic Java Collections Interview Questions
What is the Java Collections Framework?
The Java Collections Framework (JCF) is a unified architecture of interfaces (List, Set, Queue, Map) and implementations (ArrayList, HashSet, LinkedList, HashMap, etc.) plus algorithms (sorting, searching) in java.util
.
What is the difference between Collection and Collections in Java?
Collection
is the root interface for groups of objects. Collections
is a utility class with static helpers like sort
, reverse
, shuffle
, synchronizedList
, and unmodifiableList
.
List<Integer> nums = new ArrayList<>(List.of(3,1,2));
Collections.sort(nums); // [1,2,3]
List<Integer> ro = Collections.unmodifiableList(nums);
What is the difference between an Array and an ArrayList?
Arrays are fixed-size and can hold primitives or objects; ArrayList
is resizable and holds objects only.
int[] a = {1,2,3}; // fixed size
List<Integer> list = new ArrayList<>();
list.add(1); list.add(2); list.add(3); // dynamic size
What are the main interfaces in the Java Collections Framework?
Core interfaces are Collection
, List
, Set
, Queue
, and Map
. They define contracts for ordering, uniqueness, and key/value relationships.
What is the difference between a List and a Set?
A List
preserves order and allows duplicates; a Set
forbids duplicates and may or may not maintain order depending on implementation.
What is the difference between HashSet, LinkedHashSet, and TreeSet?
HashSet
is fastest and unordered, LinkedHashSet
maintains insertion order, TreeSet
keeps elements sorted.
Set<String> hs = new HashSet<>(List.of("b","a","c")); // order not guaranteed
Set<String> lhs = new LinkedHashSet<>(List.of("b","a","c")); // insertion order
Set<String> ts = new TreeSet<>(List.of("b","a","c")); // [a,b,c]
What is the difference between Map and HashMap?
Map
is an interface for key/value mappings; HashMap
is a hash table–based Map implementation.
Can a HashMap have duplicate keys or values?
Keys must be unique; values can repeat. Inserting a key again overwrites the value.
Map<String,Integer> m = new HashMap<>();
m.put("apple",1);
m.put("apple",3); // overwrites; "apple" -> 3
What is the default load factor of a HashMap?
0.75f
, which balances memory and speed by resizing when ~75% full.
Is HashMap synchronized?
No. Use Collections.synchronizedMap(map)
or ConcurrentHashMap
for thread safety.
Map<String,Integer> sync = Collections.synchronizedMap(new HashMap<>());
Is LinkedList singly or doubly linked?
LinkedList
is a doubly linked list, enabling O(1) insertions/removals at ends.
What is the difference between Iterator and ListIterator?
Iterator
works on all collections with forward traversal; ListIterator
works on Lists with bidirectional traversal and index operations.
List<String> l = new ArrayList<>(List.of("a","b","c"));
ListIterator<String> it = l.listIterator(l.size());
while (it.hasPrevious()) System.out.print(it.previous()); // "cba"
What is the difference between Enumeration and Iterator?
Enumeration
is legacy and read-only; Iterator
supports removal via remove()
and is preferred.
What is a Deque in Java?
Deque
is a double-ended queue; ArrayDeque
is a fast, resizable implementation.
Deque<Integer> dq = new ArrayDeque<>();
dq.addFirst(1); dq.addLast(2); // [1,2]
dq.removeLast(); // [1]
What is the difference between Queue and PriorityQueue?
Queue
is typically FIFO; PriorityQueue
removes elements by priority (natural order or comparator).
Queue<Integer> q = new ArrayDeque<>(List.of(3,1,2));
PriorityQueue<Integer> pq = new PriorityQueue<>(List.of(3,1,2));
System.out.println(q.poll()); // 3 (FIFO)
System.out.println(pq.poll()); // 1 (min first)
How do you implement a Queue using LinkedList?
Use LinkedList
(which implements Deque
) to get O(1) enqueue/dequeue at the ends.
Queue<String> queue = new LinkedList<>();
queue.offer("A"); queue.offer("B");
System.out.println(queue.poll()); // "A"
How does HashMap work internally (hashing, buckets, equals/hashCode)?
Keys are hashed to buckets; within a bucket, keys are checked via equals
. From Java 8, long chains become balanced trees.
class Key {
final String s;
Key(String s){ this.s = s; }
@Override public boolean equals(Object o){ return o instanceof Key k && s.equals(k.s); }
@Override public int hashCode(){ return s.hashCode(); }
}
Map<Key,Integer> map = new HashMap<>();
map.put(new Key("x"), 1);
System.out.println(map.get(new Key("x"))); // 1 (thanks to equals/hashCode)
Comparable vs Comparator with examples
Use Comparable
for natural order; Comparator
for custom orders.
class Person implements Comparable<Person>{
final String name; final int age;
Person(String n,int a){ name=n; age=a; }
@Override public int compareTo(Person o){ return name.compareTo(o.name); }
}
List<Person> people = new ArrayList<>(List.of(
new Person("Zoe",30), new Person("Ana",25)));
Collections.sort(people); // by name
people.sort(Comparator.comparingInt(p -> p.age)); // by age
Can TreeMap store null keys?
No; using a null key throws NullPointerException
. Use HashMap
if you need a null key.
Map<String,Integer> tm = new TreeMap<>();
// tm.put(null, 1); // NPE
Make a read-only and a thread-safe collection
List<String> list = new ArrayList<>(List.of("a","b"));
List<String> ro = Collections.unmodifiableList(list);
List<String> ts = Collections.synchronizedList(list);
Use LinkedHashMap to build an LRU cache
class LruCache<K,V> extends LinkedHashMap<K,V>{
private final int cap;
LruCache(int cap){ super(16, 0.75f, true); this.cap = cap; }
@Override protected boolean removeEldestEntry(Map.Entry<K,V> e){ return size() > cap; }
}
LruCache<Integer,String> cache = new LruCache<>(2);
cache.put(1,"A"); cache.put(2,"B"); cache.get(1); cache.put(3,"C"); // evicts key 2
Technical interviews often include Java collections interview questions, so mastering them is essential. If you want a complete list beyond collections, check out our 150+ Killer Core Java Interview Questions and Answers (Crack Any Job) guide
Advanced Java Collections Interview Questions
How does HashMap handle collisions (list vs tree bins)?
Collisions are stored in a bucket as a linked list; if a bucket grows beyond a threshold and keys are comparable, it becomes a balanced tree (improves worst-case from O(n) to O(log n)).
What is the difference between fail-fast and fail-safe iterators?
Fail-fast iterators throw ConcurrentModificationException
. Fail-safe iterators iterate over a snapshot or segmented structure and keep going.
// Fail-fast example
List<Integer> a = new ArrayList<>(List.of(1,2,3));
for (Integer x : a) {
if (x == 2) a.add(4); // throws ConcurrentModificationException
}
// Fail-safe example with CopyOnWriteArrayList
List<Integer> cow = new CopyOnWriteArrayList<>(List.of(1,2,3));
for (Integer x : cow) {
if (x == 2) cow.add(4); // safe; iterator sees old snapshot
}
How does TreeMap keep order and what is its complexity?
TreeMap
uses a Red-Black Tree sorted by keys; get/put/remove
are O(log n).
Map<String,Integer> tm = new TreeMap<>();
tm.put("b",2); tm.put("a",1); tm.put("c",3);
System.out.println(tm.keySet()); // [a, b, c]
HashMap vs Hashtable vs ConcurrentHashMap
HashMap
is unsynchronized; Hashtable
is legacy, fully synchronized; ConcurrentHashMap
is modern, high-throughput with fine-grained concurrency.
Map<String,Integer> chm = new ConcurrentHashMap<>();
chm.put("a",1);
chm.compute("a", (k,v) -> v+1); // atomic update
IdentityHashMap and reference equality
IdentityHashMap
compares keys with ==
not equals
.
IdentityHashMap<String,Integer> ih = new IdentityHashMap<>();
ih.put(new String("x"), 1);
ih.put(new String("x"), 2); // different references -> both entries exist
System.out.println(ih.size()); // 2
WeakHashMap and garbage-collected keys
Keys are weakly referenced; when a key has no strong refs, the entry is eligible for removal.
Map<Object,String> whm = new WeakHashMap<>();
Object k = new Object();
whm.put(k, "val");
k = null; // after GC, mapping may disappear
ArrayList vs Vector vs CopyOnWriteArrayList
ArrayList
is fast and unsynchronized; Vector
is synchronized; CopyOnWriteArrayList
is thread-safe and great for read-heavy workloads.
CopyOnWriteArrayList<String> safeList = new CopyOnWriteArrayList<>();
safeList.add("a"); safeList.addIfAbsent("a"); // de-dup helper
LinkedHashMap vs HashMap (insertion vs access order)
LinkedHashMap
supports insertion order or access order, enabling LRU patterns (see Basic section for LRU code).
EnumSet and EnumMap for enum-optimized collections
enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }
EnumSet<Day> weekend = EnumSet.of(Day.SAT, Day.SUN);
EnumMap<Day,String> plan = new EnumMap<>(Day.class);
plan.put(Day.MON, "Gym");
Stack vs Deque for stack operations
Prefer Deque
via ArrayDeque
for push/pop.
Deque<Integer> stack = new ArrayDeque<>();
stack.push(10); stack.push(20);
System.out.println(stack.pop()); // 20
Why is HashSet usually faster than TreeSet?
Average O(1) vs O(log n) for add/contains/remove. Choose TreeSet
when you need sorted order or range queries.
PriorityQueue vs TreeSet (duplicates and ordering)
PriorityQueue
allows duplicates and retrieves by head priority; TreeSet
forbids duplicates and supports full sorted set operations.
PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder()); // max-heap
pq.addAll(List.of(5,1,5));
System.out.println(pq.poll()); // 5 (top priority)
What is a BlockingQueue and when to use it?
A BlockingQueue
blocks producers when full and consumers when empty-ideal for producer/consumer.
BlockingQueue<Integer> bq = new ArrayBlockingQueue<>(2);
new Thread(() -> { try { bq.put(1); bq.put(2); bq.put(3); } catch(Exception ignored){} }).start();
new Thread(() -> { try { Thread.sleep(200); System.out.println(bq.take()); } catch(Exception ignored){} }).start();
DelayQueue vs PriorityQueue
DelayQueue
releases elements only after their delay expires.
class Task implements Delayed {
final long runAt; final String name;
Task(String n, long delayMs){ name=n; runAt=System.currentTimeMillis()+delayMs; }
public long getDelay(TimeUnit u){ return u.convert(runAt-System.currentTimeMillis(), TimeUnit.MILLISECONDS); }
public int compareTo(Delayed d){ return Long.compare(runAt, ((Task)d).runAt); }
}
DelayQueue<Task> dq = new DelayQueue<>();
dq.put(new Task("T1", 500));
What is ConcurrentLinkedQueue?
A non-blocking, lock-free FIFO queue based on CAS-great for high-throughput, low-latency pipelines.
Queue<Integer> clq = new ConcurrentLinkedQueue<>();
clq.offer(1); clq.offer(2);
System.out.println(clq.poll()); // 1
NavigableMap and NavigableSet operations
Useful for nearest-neighbor lookups.
NavigableMap<Integer,String> nm = new TreeMap<>();
nm.put(10,"A"); nm.put(20,"B"); nm.put(30,"C");
System.out.println(nm.floorEntry(25)); // 20=B
System.out.println(nm.ceilingKey(21)); // 30
NavigableSet<Integer> ns = new TreeSet<>(List.of(10,20,30));
System.out.println(ns.lower(20)); // 10
TreeMap vs LinkedHashMap
TreeMap
sorts by key; LinkedHashMap
maintains insertion or access order. Choose based on retrieval semantics (sorted vs predictable iteration).
Duplicate handling in HashSet and TreeSet
HashSet
ignores duplicates based on equals/hashCode
; TreeSet
ignores duplicates based on comparator/natural order.
Set<String> s = new HashSet<>();
s.add("x"); s.add("x"); // still size 1
Make unmodifiable views of collections
Set<String> base = new HashSet<>(Set.of("a","b"));
Set<String> roSet = Collections.unmodifiableSet(base);
Make collections thread-safe: synchronized vs concurrent
List<Integer> syncList = Collections.synchronizedList(new ArrayList<>());
Map<String,Integer> concMap = new ConcurrentHashMap<>();
Shallow copy vs deep copy in collections
// Shallow copy (elements shared)
List<List<Integer>> a = new ArrayList<>();
a.add(new ArrayList<>(List.of(1,2)));
List<List<Integer>> shallow = new ArrayList<>(a);
shallow.get(0).add(3); // also visible in 'a'
// Deep copy (elements duplicated)
List<List<Integer>> deep = new ArrayList<>();
for (List<Integer> inner : a) deep.add(new ArrayList<>(inner));
ConcurrentSkipListMap and ConcurrentSkipListSet
Sorted, concurrent structures useful when you need ordered maps/sets with multi-threaded access.
ConcurrentSkipListMap<Integer,String> csm = new ConcurrentSkipListMap<>();
csm.put(2,"B"); csm.put(1,"A");
System.out.println(csm.firstEntry()); // 1=A
ArrayDeque vs LinkedList as a Deque
ArrayDeque
is typically faster and more cache-friendly; LinkedList
has node overhead but supports constant-time removals given a node reference.
Custom Comparator examples (multi-field, null-safe)
record Emp(String name, Integer score) {}
List<Emp> emps = new ArrayList<>(List.of(
new Emp("Ana", 90), new Emp("Bob", null), new Emp("Ana", 85)));
Comparator<Emp> cmp = Comparator
.comparing(Emp::name)
.thenComparing(Comparator.comparing(Emp::score, Comparator.nullsLast(Integer::compareTo)));
emps.sort(cmp);
Spliterator basics (parallel iteration support)
Spliterators describe characteristics for efficient parallel processing.
List<Integer> data = IntStream.range(0, 1_000).boxed().toList();
int sum = data.parallelStream().mapToInt(i->i).sum();
Using Collectors
with collections
Map<Integer, Long> freq = Stream.of(1,2,2,3,3,3)
.collect(Collectors.groupingBy(i -> i, Collectors.counting())); // {1=1, 2=2, 3=3}
Immutable collections (Java 9+ factory methods)
List<String> imm = List.of("a","b","c"); // truly immutable
Set<Integer> immSet = Set.of(1,2,3);
When to choose Map implementations (HashMap/LinkedHashMap/TreeMap)
HashMap
: fastest general useLinkedHashMap
: predictable iteration or LRUTreeMap
: sorted keys and range queries
When to choose Set implementations (HashSet/LinkedHashSet/TreeSet)
HashSet
: membership tests, no orderLinkedHashSet
: dedupe with stable iteration orderTreeSet
: sorted set, range operations
When to choose List implementations (ArrayList/LinkedList/CopyOnWriteArrayList)
ArrayList
: random access, append heavyLinkedList
: frequent middle insert/removeCopyOnWriteArrayList
: many readers, few writers
Bulk operations and performance tips
Prefer addAll
, removeIf
, replaceAll
, computeIfAbsent
, and streams for clarity and performance.
Map<String,List<Integer>> idx = new HashMap<>();
idx.computeIfAbsent("k", k -> new ArrayList<>()).add(42);
Related Java Interview Guides
- 150+ Killer Core Java Interview Questions and Answers (Crack Any Job)
- Complete Basic Java Interview Questions and Answers with Tips
- Top 30 Java Interview Questions for Freshers (Expert Tips Included)
- 75+ Java Multithreading Interview Questions & Answers (Basic to Advanced)
FAQ
What are the most commonly asked Java collections interview questions?
Interviewers frequently ask about differences among List, Set, Map; HashMap internals (hashing, buckets, tree bins), ArrayList vs LinkedList trade-offs, Comparable vs Comparator, fail-fast vs fail-safe iterators, and concurrent collections like ConcurrentHashMap and CopyOnWriteArrayList.
Which collection should I use for fast lookups?
Use HashMap
for key→value lookups and HashSet
for membership checks. Both provide average O(1) time for add/get/contains, assuming good hashCode
and equals
implementations.
When should I prefer TreeMap or TreeSet over HashMap/HashSet?
Choose TreeMap
/TreeSet
when you need sorted order, range queries (subMap
, headSet
, tailSet
), or navigation methods (ceiling
, floor
). Expect O(log n) operations.
Why is my HashMap returning null for an equal key?
Likely equals
/hashCode
are inconsistent or mutable fields used in hashing changed after insertion. Ensure both are consistent, use immutable keys, and avoid mutating fields that participate in hashing.
How do I implement an LRU cache quickly?
Use LinkedHashMap
with access order:
new LinkedHashMap<K,V>(16, 0.75f, true) {
protected boolean removeEldestEntry(Map.Entry<K,V> e) { return size() > MAX; }
};
What is the difference between fail-fast and fail-safe iterators?
Fail-fast iterators (e.g., on ArrayList, HashMap) throw ConcurrentModificationException
on structural change. Fail-safe iterators (e.g., CopyOnWriteArrayList, ConcurrentHashMap views) iterate over a snapshot or concurrent structure and do not throw.
Can HashMap have a null key? Can TreeMap?
HashMap
allows one null
key and many null
values. TreeMap
does not allow null
keys because it needs to compare keys.
When should I use CopyOnWriteArrayList?
Use it for read-heavy, write-light workloads (e.g., listener lists). Iteration is snapshot-based and lock-free; writes copy the underlying array and are expensive.
How do I make a collection unmodifiable?
Wrap with the unmodifiable views or use Java 9+ factory methods:
List<String> ro1 = Collections.unmodifiableList(mutable);
List<String> ro2 = List.of("a","b","c"); // truly immutable
What’s the fastest way to count frequencies?
Use Map.merge
or streams:
map.merge(key, 1, Integer::sum);
// or
Stream.of(1,2,2,3).collect(Collectors.groupingBy(x->x, Collectors.counting()));
How do I avoid ConcurrentModificationException
during iteration?
Use iterator’s remove()
instead of collection.remove()
, iterate over a snapshot, or use concurrent collections (e.g., ConcurrentHashMap
, CopyOnWriteArrayList
) depending on the use case.
How do I convert between collections efficiently?
Use constructors and addAll
, or streams:
Set<String> s = new HashSet<>(list);
List<String> l = new ArrayList<>(set);
List<Integer> r = stream.collect(Collectors.toList());
What are best practices for keys in maps?
Prefer immutable, well-encapsulated keys with stable equals
/hashCode
. Avoid using mutable fields in those methods and consider record
types for simple value objects.
How do I choose between ArrayDeque and LinkedList for a queue/stack?
Prefer ArrayDeque
for better locality and lower overhead. Use LinkedList
only if you need constant-time removals given a node reference.
How do I safely iterate and modify a Map concurrently?
Use ConcurrentHashMap
and atomic operations (compute
, merge
, putIfAbsent
). Its iterators are weakly consistent and won’t throw ConcurrentModificationException
.
Conclusion
Mastering the Java Collections Framework is a must for any developer preparing for technical interviews. From the basics of List, Set, Map, and Queue to advanced concepts like ConcurrentHashMap, WeakHashMap, and BlockingQueue, collections are everywhere in Java. Interviewers often test both theory (differences, complexity, use cases) and practical knowledge (code, iteration, concurrency pitfalls).
By practicing these Java collections interview questions and answers with examples, you will be able to:
- Confidently explain how collections work internally
- Choose the right collection for a given problem
- Avoid common pitfalls like ConcurrentModificationException
- Demonstrate knowledge of thread-safe and immutable collections
If you understand not just what each collection does, but also why and when to use it, you’ll be ready to ace any Java interview in 2025 and beyond.
Pro tip: Bookmark this guide and revisit it during your prep.
Next step: Practice these concepts by writing small programs-real coding practice will reinforce your understanding and help you shine in interviews.
If you understand not just what each collection does, but also why and when to use it, you’ll be ready to ace any Java interview in 2025 and beyond. For broader coverage, explore our 150+ Killer Core Java Interview Questions and Answers (Crack Any Job).