Java Collection Framework Interview Questions & Answers
This guide compiles real, advanced, and tricky interview questions on the Java Collection Framework commonly asked of experienced developers (2–7 years experience).
1. General Collection Framework Concepts
Why doesn't the Collection framework have a common interface for both List and Map?
The Java collection framework is organized like a tree structure. It has two major branches: the Collection interface (containing List, Set, and Queue) and the Map interface. They store and handle data differently. A List stores elements as a single collection of values using indexes. A Map stores data as key-value pairs linked to unique keys. Since their structure, behavior, and methods are entirely different, a single common interface would not make sense and would be either too generic or confusing.
What problem would arise if collections allowed primitive types?
Collections in Java are designed to work with objects, not raw primitive values. They rely heavily on object-oriented features like generics, inheritance, and methods defined in the Object class (like equals and hashCode). Primitive types don't support these features, so they wouldn't fit into the collection design.
Can you design your own collection and what methods are mandatory?
Yes, you can design your own collection by either implementing the Collection interface directly or extending an existing abstract class like AbstractList or AbstractSet.
- If implementing a List, you must define
get()andset()methods. - If implementing a Map, you must define
put(),get(), andremove()methods.
2. Equals & HashCode Contract
What is the equals and hashCode contract?
It is a fundamental rule in Java that keeps object comparison and hashing consistent:
equals()is used to check if two objects are logically equal (have the same data).hashCode()returns an integer representing the object for fast searching and deciding hash buckets.- The Rules: If two objects are equal via
equals(), theirhashCode()must be the same. If two objects have the same hash code, they are not necessarily equal. If you overrideequals(), you must also overridehashCode(). During execution,hashCode()should return the same value unless object data changes.
What happens if the equals method is overridden but hashCode is not?
equals() may indicate that two objects are identical, but their hash codes will be different. Consequently, they will be stored in entirely different buckets. This can cause duplicate objects to be stored in a HashMap or HashSet, and searching for an existing object might fail even if it is logically present.
Can two unequal objects have the same hash code?
Yes, two unequal objects can produce the same hash code. This is known as a hash collision. Hash codes are just numbers used to quickly group objects. Since the range of integer values is limited and the number of potential objects is vast, different objects may inevitably produce the same hash value.
What breaks if mutable fields are used in hashCode?
If mutable (changeable) fields are used in a hash code, it breaks hash-based collections. When an object is added, its hash code determines its bucket. If a field changes later, its hash code also changes. When Java searches for the object using its new hash code, it looks in a different bucket and cannot find it, causing data retrieval to fail.
3. List Interface
Explain the internal working of ArrayList.
ArrayList works like a dynamic array:
- Storage: Internally stores elements in a standard array in ordered fashion.
- Initial Capacity: Usually starts with a default capacity of 10.
- Adding Elements: Places new items in the next free index.
- Resizing: If the array becomes full, a new, bigger array (1.5 times the old size) is created. Old elements are copied over, and new elements are added.
- Performance: Fast for reading ($O(1)$) because it is index-based. Slow for removals ($O(n)$) because elements must shift left to fill gaps.
Can ArrayList store null multiple times?
Yes, ArrayList can store null multiple times. null is treated like any normal element and can be added and stored at different indexed positions.
Why is LinkedList slower for search operations?
LinkedList does not use indexing like an array. Its elements are connected using nodes, where each node points to the next. To search for an element, Java must start from the very first node and traverse them sequentially until it reaches the target, which is slower ($O(n)$).
What are the use cases of ArrayList vs. LinkedList?
- Use
ArrayListwhen you need fast reading, searching by index, frequent access, and have more read operations than insert/delete operations. - Use
LinkedListwhen you need frequent insertions and deletions (especially at the beginning or middle) or when building Queue/Stack type structures.
What happens if you modify a list while iterating using a for-each loop?
If you modify a list while actively iterating it using a for-each loop, Java will usually throw a ConcurrentModificationException.
4. Set Interface
How does a Set ensure uniqueness without knowing object equality logic?
A Set ensures uniqueness by utilizing the hashCode() and equals() methods of the object itself. When an object is added, it checks the hash code to decide which bucket to store it in. If another object is found with the same hash code, it calls the equals() method to compare them. If true, it's a duplicate and is rejected. If false, it's safely added.
Does Set allow null values?
It depends on the specific implementation:
HashSetandLinkedHashSetallow exactly onenullvalue.TreeSetdoes not allownullvalues and will throw an error (because it cannot comparenullfor sorting).
Why is there no get() method in a Set?
A Set is not index-based. It simply stores unique elements and does not maintain position or indexes. Its primary focus is determining if an element is present or not. Since there is no fixed index, get(0) makes no sense.
Why is TreeSet slower than HashSet?
TreeSet is slower because it strictly maintains elements in a sorted order. This overhead of comparing and sorting takes extra time for insertions, deletions, and searches ($O(\log n)$) compared to the near-instant hashing operations ($O(1)$) of HashSet.
How does LinkedHashSet maintain insertion order?
It works like a HashSet internally using hash codes for storage, but it also maintains a doubly-linked list that connects elements in the exact order they were added. During iteration, it simply follows this linked list.
5. Map Interface
Why does Map not extend Collection?
Collections store single values, while Maps store key-value pairs. Their fundamental structures and functional methods are completely different, so Map is kept entirely separate from the Collection interface hierarchy.
Why are keys required to be unique, but values are not?
Keys are the identifiers used to retrieve data. If two keys were identical, Java wouldn't know which specific value to return. Values are just the payload data, so duplicates are perfectly fine.
Why does Map expose entrySet() instead of iterating directly?
A Map entry has two distinct parts: Key and Value. entrySet() packages both together as a pair, making it much more efficient to loop through and access both simultaneously rather than looping keys and doing individual lookups.
Explain the internal working of HashMap.
- Hashing the Key: Java takes the key and calls its
hashCode()method to generate an integer. - Bucket Location: This number decides which bucket in an internal array the data will be routed to.
- Storing Entry: The key and value are stored as an object pair in that specific bucket.
- Collision Handling: If multiple keys end up in the same bucket, they are stored as a linked list. In modern Java, if this list gets too long, it converts to a Red-Black tree for faster searches.
- Retrieval: When calling
get(), it finds the bucket via hash code, then loops through the bucket usingequals()to find the precise key and return its value.
What is the default capacity and load factor of HashMap?
- Default Capacity: 16 (the number of starting buckets).
- Load Factor: 0.75. This means when 75% of the buckets are filled (e.g., adding the 13th entry in a 16-bucket map), the
HashMapresizes itself to avoid performance drops.
What happens internally when two keys have the same hash?
This is a collision. Both keys are routed to the same bucket. The HashMap then uses their equals() methods to confirm they are distinct and stores them separately inside that same bucket (usually in a linked list or tree).
What if equals() is true but the hash code is different?
The HashMap will treat them as two completely different keys and store them in different buckets. When you later try to search for it, the operation may fail because the algorithm looks in the wrong bucket. This thoroughly breaks expected HashMap behavior.
Why does HashMap allow one null key?
HashMap handles null explicitly as a special case and always stores it in a fixed bucket (index 0). Because keys must be unique, only a single null key is ever permitted.
Explain the internal working of LinkedHashMap and its use in LRU Caches.
It works exactly like a HashMap but also keeps a doubly-linked list running through all its entries to remember insertion or access order.
- LRU Cache Implementation: When set to "access order mode", every time you
getorputa key, it moves to the end of the list. The least recently used item remains at the very beginning. When the cache hits capacity, you easily drop the first entry.
Explain the internal working of TreeMap.
TreeMap stores key-value pairs sorted strictly by keys.
- Red-Black Tree: Internally uses a self-balancing tree structure.
- No Hashing: It completely bypasses hash codes. Instead, it relies on
compareTo()or a customComparatorto navigate left or right through the tree. - Null Keys: It does not allow
nullkeys, as callingcompareTo()onnulltriggers aNullPointerException.
6. Thread Safety & Concurrent Collections
How to make standard collections thread-safe?
You can wrap standard collections using Collections.synchronizedList(), Collections.synchronizedSet(), or Collections.synchronizedMap().
Which is better: Collections.synchronizedMap() or ConcurrentHashMap?
ConcurrentHashMap is far superior for most real-world applications. synchronizedMap() locks the entire map when a thread uses it, creating a severe bottleneck. ConcurrentHashMap uses "fine-grained locking" (locking only individual buckets internally), allowing many threads to read and write safely at the same time.
Explain the internal working of ConcurrentHashMap.
- It is a thread-safe implementation of
HashMap. - No Full Lock: It does not lock the entire map. It locks only the specific bucket where an update is occurring.
- Lock-Free Reads: Threads can read data simultaneously without waiting.
- No Exceptions: It allows safe modifications during iterations using snapshot views, preventing
ConcurrentModificationException.
Why doesn't ConcurrentHashMap allow null values or keys?
In a multi-threaded environment, null introduces ambiguity. If get(key) returns null, it's impossible to know immediately if the key does not exist or if the value stored is genuinely null. Prohibiting null avoids this concurrency confusion.
What is CopyOnWriteArrayList and its use cases?
It is a highly thread-safe list where every operation that alters it (add, remove, update) triggers the creation of a completely new copy of the underlying array.
- Use Cases: Highly effective when read operations are extremely frequent and write operations are very rare (e.g., storing configuration data or listener lists).
- Safe Iterations: Because iterators look at a static snapshot of the array,
ConcurrentModificationExceptionis inherently avoided.
Why doesn't synchronizing Vector automatically make it completely safe?
While Vector locks its individual methods, compound operations (e.g., checking if an item exists and then removing it) are still not thread-safe. Iterating over a Vector also requires manual synchronization blocks to be genuinely safe.
7. Iterators & Comparators
What is the difference between Fail-Fast and Fail-Safe Iterators?
- Fail-Fast: Throws a
ConcurrentModificationExceptionimmediately if the collection is altered structurally during iteration (Examples:ArrayList,HashMap). - Fail-Safe: Works on a clone or snapshot of the collection, so it does not throw exceptions if the collection is modified (Examples:
CopyOnWriteArrayList,ConcurrentHashMap).
What is the difference between Comparable and Comparator?
- Comparable: The sorting logic is written internally inside the class itself (using
compareTo()). It allows for only one default natural sorting style. - Comparator: The sorting logic is written externally in separate classes (using
compare()). This enables creating multiple, different sorting strategies (e.g., sorting by name, by age, by salary).
8. Queue, Deque, and Legacy Classes
Explain PriorityQueue, Deque, ArrayDeque, and Stack.
- PriorityQueue: A Queue where elements are processed based on their inherent priority (lowest to highest, or custom logic) rather than insertion order. Used in task scheduling and shortest-path algorithms.
- Deque: A double-ended queue allowing insertion and removal from both the front and back. Used heavily in sliding window problems or caching.
- ArrayDeque: An implementation of Deque backed by an array. It is significantly faster than using a
Stack(for LIFO) or aLinkedList(for FIFO). - Stack: A legacy class enforcing LIFO (Last-In, First-Out). Commonly used for undo mechanisms or tracking history. It is mostly replaced by
ArrayDequein modern Java.