Choosing the Right Collection
Fast recall
Quick revision
Core answer
ArrayList for random access, ArrayDeque for queues).Whether you have a repeatable decision process rather than memorized defaults
Jumping straight to ArrayList/HashMap without asking about uniqueness, ordering, or lookup
Phrase it as a decision tree and mention thread-safety (ConcurrentHashMap) as a final branch
Interview-ready guide
Interview answer
I treat it as a short decision tree rather than memorizing defaults.
The first question is about the shape of the data: am I looking things up by a key? If the access pattern is given an id, fetch the object, then I need a Map, because that turns lookups into constant time instead of scanning a list. If I'm not looking up by key, the next question is whether duplicates are allowed.
If duplicates are fine and order matters, I want a List — ArrayList by default, or ArrayDeque if it's really a queue or a stack. If elements must be unique, I want a Set. Once the family is decided, I choose the variant by ordering needs.
The Hash variant is fastest and has no order, the Linked variant preserves insertion order, and the Tree variant keeps things sorted and supports range queries, at log-n cost. So for a Map I'd pick HashMap, LinkedHashMap, or TreeMap, and for a Set, HashSet, LinkedHashSet, or TreeSet, using the same logic. The last branch I always check is thread safety.
If the structure is shared across threads, I don't use the plain version — I reach for ConcurrentHashMap, or CopyOnWriteArrayList for read-heavy lists. When none of these special needs apply, the safe defaults are ArrayList and HashMap. Walking through the questions out loud — key lookup, duplicates, ordering, access pattern, concurrency — shows the interviewer I have a real process, not just a memorized answer.
Choosing the Right Collection
Direct Answer
Ask a short decision sequence: do you need key-value lookup (Map) or just elements? Must elements be unique (Set) or are duplicates allowed (List)? Then pick the variant by ordering (Hash = none, Linked = insertion, Tree = sorted) and access pattern (ArrayList for random access, ArrayDeque for queues).
Code Example
import java.util.*;
import java.util.concurrent.*;
// Lookup by key -> Map (sorted keys -> TreeMap)
Map<String, Product> byId = new HashMap<>();
// Unique tags, insertion order -> LinkedHashSet
Set<String> tags = new LinkedHashSet<>();
// Ordered feed with duplicates, random access -> ArrayList
List<String> feed = new ArrayList<>();
// FIFO queue -> ArrayDeque
Deque<String> jobs = new ArrayDeque<>();
// Shared across threads -> concurrent variant
Map<String, Integer> liveCounts = new ConcurrentHashMap<>();
Each declaration answers one question: lookup, uniqueness, ordering, access pattern, and concurrency.
Common Mistakes & Pitfalls
- Reaching for
ArrayListon reflex. Always ask about lookup, uniqueness, and ordering first — the right structure often is not a list at all. - Scanning a
Listwithcontainsfor uniqueness. That is O(n) per check; aSetdoes it in O(1) and rejects duplicates automatically. - Using
LinkedListas a default list.ArrayListwins for almost everything;LinkedList.get(i)inside a loop is O(n^2). - Forgetting thread safety. A shared
HashMapunder concurrent writes can corrupt; useConcurrentHashMapwhen multiple threads touch it.
Check your understanding
Answer these without looking back at the article.
- When would you use a PriorityQueue?
- How do you store unique elements in insertion order?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.