Interview Prep
Interview Questions on Collection Framework in Java — List, Set, Map, and Internal Working
The Java Collection Framework is tested in every Java interview — from campus placements to senior developer rounds. Interviewers do not just ask “what is ArrayList?” They ask how HashMap works internally, when to use LinkedHashMap, and how ConcurrentHashMap handles thread safety. Here is the deep dive.

The Collection Framework is the most tested Java topic after OOPs. Every interview from TCS to Amazon asks about it.
Why Collection Framework Dominates Java Interviews
The Java Collection Framework provides the data structures that every Java application uses — List, Set, Map, Queue. In interviews, it is the bridge between theory (data structures) and practice (which Java class to use). Interviewers test three things: which collection to use for a given scenario, how the collection works internally, and the performance characteristics (Big O) of each operation.
This guide goes deeper than basic definitions. It covers the internal working of HashMap, the difference between fail-fast and fail-safe iterators, and the concurrent collections that senior interviews test.
“How does HashMap work internally?” is the single most asked Java interview question in India. If you cannot explain hashing, buckets, and collision handling, the interview is over.
Collection Framework Hierarchy
Q1: Draw the Collection Framework hierarchy.
Iterable
│
Collection
/ | \
List Set Queue
/ | \ | \ | \
ArrayList | Vector HashSet TreeSet PriorityQueue ArrayDeque
LinkedList Stack LinkedHashSet
Map (separate hierarchy)
/ | \
HashMap TreeMap Hashtable
|
LinkedHashMap
|
ConcurrentHashMap
Key interfaces:
- Collection → root interface (add, remove, contains)
- List → ordered, allows duplicates, index access
- Set → no duplicates
- Queue → FIFO ordering
- Map → key-value pairs (NOT part of Collection interface)
// This hierarchy question is asked in 80% of interviews.
// Draw it from memory.List Interface Deep Dive
Q2: ArrayList vs LinkedList vs Vector — complete comparison.
Feature ArrayList LinkedList Vector
────────── ────────── ────────── ──────────
Internal Dynamic array Doubly linked Dynamic array
list
Access O(1) random O(n) random O(1) random
Insert/Delete O(n) middle O(1) if at node O(n) middle
Thread-safe No No Yes (synchronized)
Growth 50% increase N/A 100% increase
Memory Less overhead More (pointers) Less overhead
Iterator Fail-fast Fail-fast Fail-fast
// When to use:
// ArrayList → default choice (95% of cases)
// LinkedList → frequent insert/delete at both ends (Queue)
// Vector → legacy, use Collections.synchronizedList() instead
// ArrayList internal working:
// Default capacity: 10
// When full: creates new array of size (old * 1.5)
// Copies all elements to new array
// This is why add() is amortized O(1) but worst case O(n)
ArrayList<String> list = new ArrayList<>(50); // set initial capacity
// If you know the size, set initial capacity to avoid resizingQ3: How do you make an ArrayList thread-safe?
// Method 1: Collections.synchronizedList()
List<String> syncList = Collections.synchronizedList(
new ArrayList<>()
);
// Wraps every method with synchronized block
// Must manually synchronize during iteration:
synchronized (syncList) {
for (String s : syncList) {
System.out.println(s);
}
}
// Method 2: CopyOnWriteArrayList (preferred for read-heavy)
List<String> cowList = new CopyOnWriteArrayList<>();
// Creates a new copy of array on every write
// Reads are lock-free (fast)
// Writes are expensive (copies entire array)
// Best for: read-heavy, write-rare scenarios (listeners)
// Method 3: Vector (legacy — avoid)
Vector<String> vector = new Vector<>();
// Every method is synchronized — too much overheadMap Interface — The Most Tested Topic
Q4: How does HashMap work internally? (Complete answer)
// HashMap = array of buckets (Node<K,V>[]) // Each bucket = linked list (or tree if > 8 nodes) // PUT operation: // 1. key.hashCode() → raw hash // 2. hash = hash ^ (hash >>> 16) → spread bits // 3. index = hash & (capacity - 1) → bucket index // 4. If bucket empty → store Node directly // 5. If bucket has nodes: // a. Check each node: if key.equals(existingKey) // → update value (replace) // b. If no match → add to end of linked list // c. If list length > 8 → convert to red-black tree // GET operation: // 1. Calculate hash → find bucket index // 2. Traverse bucket (list or tree) // 3. Use equals() to find exact key match // Key constants: // Default capacity: 16 // Load factor: 0.75 (resize when 75% full) // Treeify threshold: 8 (list → tree) // Untreeify threshold: 6 (tree → list) // Resize (rehashing): // When size > capacity * loadFactor // New capacity = old capacity * 2 // ALL entries are rehashed to new buckets // This is expensive — set initial capacity if possible HashMap<String, Integer> map = new HashMap<>(100, 0.75f);
Q5: HashMap vs Hashtable vs ConcurrentHashMap
Feature HashMap Hashtable ConcurrentHashMap ────────── ────────── ────────── ────────────────── Thread-safe No Yes (all sync) Yes (segment-level) Null keys 1 null key No null keys No null keys Null values Multiple No null values No null values Performance Fastest Slowest Fast (concurrent) Iterator Fail-fast Fail-fast Weakly consistent Since Java 1.2 Java 1.0 Java 1.5 // ConcurrentHashMap internal (Java 8+): // Uses CAS (Compare-And-Swap) + synchronized blocks // Only locks the specific bucket being modified // Multiple threads can read/write different buckets simultaneously // Much better than Hashtable which locks the entire map // When to use: // HashMap → single-threaded (default choice) // ConcurrentHashMap → multi-threaded // Hashtable → never (legacy)
Q6: What happens if two keys have the same hashCode?
This is a collision. Both keys go to the same bucket. HashMap stores them as a linked list in that bucket. When retrieving, it traverses the list and uses equals() to find the exact key. If the list grows beyond 8 nodes (Java 8+), it converts to a red-black tree for O(log n) lookup instead of O(n).
Follow-up: “What is the contract between hashCode() and equals()?” — If two objects are equal (equals() returns true), they MUST have the same hashCode. But two objects with the same hashCode are NOT necessarily equal. Breaking this contract causes HashMap to malfunction.

HashMap internals is the most asked Java question. Know hashing, buckets, collisions, and the treeification threshold.
Set and Queue
Q7: How does HashSet work internally?
HashSet uses HashMap internally. Every element you add to a HashSet is stored as a KEY in an internal HashMap, with a dummy constant object as the value. When you call set.add("hello"), it internally calls map.put("hello", PRESENT) where PRESENT is a static dummy Object. This is why HashSet does not allow duplicates — HashMap does not allow duplicate keys.
Q8: What is the difference between Comparable and Comparator?
// Comparable — natural ordering (inside the class)
class Student implements Comparable<Student> {
String name;
int marks;
@Override
public int compareTo(Student other) {
return this.marks - other.marks; // ascending by marks
}
}
Collections.sort(students); // uses compareTo()
// Comparator — custom ordering (outside the class)
Comparator<Student> byName = (s1, s2) ->
s1.name.compareTo(s2.name);
Collections.sort(students, byName);
// Multiple sort criteria:
Comparator<Student> byMarksDesc =
Comparator.comparingInt(Student::getMarks).reversed();
Comparator<Student> byNameThenMarks =
Comparator.comparing(Student::getName)
.thenComparingInt(Student::getMarks);
// Key difference:
// Comparable = single natural order, modifies the class
// Comparator = multiple custom orders, external to classQ9: What is the difference between fail-fast and fail-safe iterators?
// Fail-fast: throws ConcurrentModificationException
// if collection is modified during iteration
// ArrayList, HashMap, HashSet use fail-fast iterators
List<String> list = new ArrayList<>(Arrays.asList("a","b","c"));
for (String s : list) {
list.remove(s); // ConcurrentModificationException!
}
// Safe way to remove during iteration:
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if (it.next().equals("b")) {
it.remove(); // safe — uses iterator's remove()
}
}
// Fail-safe: works on a COPY of the collection
// CopyOnWriteArrayList, ConcurrentHashMap use fail-safe
// No exception, but may not reflect latest changes
CopyOnWriteArrayList<String> cowList = new CopyOnWriteArrayList<>();
// Iterating while modifying is safe hereHow to Prepare
Collection Framework — Priority by Experience
Freshers
- • Hierarchy diagram
- • ArrayList vs LinkedList
- • HashMap basics
- • HashSet usage
- • Comparable vs Comparator
2-4 Years
- • HashMap internals (complete)
- • hashCode/equals contract
- • Fail-fast vs fail-safe
- • TreeMap/TreeSet
- • Collections utility class
5+ Years
- • ConcurrentHashMap internals
- • CopyOnWriteArrayList
- • BlockingQueue
- • Custom collection design
- • Performance tuning