Three common collections, three different jobs: one keeps order, one enforces uniqueness, and one processes work in line. Interviewers love this because it checks whether you choose the right tool instead of just naming classes.
Question: List vs Set vs Queue.
Answer: A List stores elements in order and allows duplicates, so you can access items by index. A Set stores unique elements only, so duplicates are rejected based on equals() and hashCode(). A Queue is for processing elements in a flow, usually first-in-first-out, where you add at one end and remove from the other.
Interview-Ready Answer: I use a List when order and index-based access matter, a Set when I need uniqueness, and a Queue when I need to process items in arrival order. For example, ArrayList is good for fast reads by index, HashSet gives average O(1) membership checks, and ArrayDeque is a strong choice for a FIFO queue because enqueue and dequeue are typically O(1). The key difference is not just the data structure name, but the rule it enforces: order, uniqueness, or processing order.
get(i) is O(1). Inserting or removing in the middle shifts later elements, so that is O(n). A practical detail interviewers like: ArrayList grows automatically, and expansion is amortized O(1) for appends.HashMap. When you add an element, Java hashes it, finds a bucket, and checks equals() to see whether the value is already there. Average contains(), add(), and remove() are O(1); the worst case can degrade toward O(n) if many items collide in the same bucket. Default HashMap load factor is 0.75, which means it grows before buckets become too crowded.ArrayDeque is a common FIFO queue: it uses a circular array, so adding at the tail and removing from the head are typically O(1). PriorityQueue is different: it uses a heap, which means the next item removed is the smallest or highest-priority one, not necessarily the oldest.| Feature | List | Set | Queue |
|---|---|---|---|
| Order | Yes | Usually no | Usually FIFO |
| Duplicates | Allowed | Not allowed | Allowed |
| Index access | Yes | No | No |
| Typical use | Sequence | Uniqueness | Processing |
| Common impl. | ArrayList | HashSet | ArrayDeque |
List when you need to preserve the exact order of items, show items in a UI, or fetch by position.Set when duplicates are a bug, such as tracking unique user IDs, tags, or visited nodes.Queue when tasks should be handled in arrival order, like jobs, messages, or retries.equals() and hashCode(), or the set may treat equal objects as different.PriorityQueue is still a queue, but it removes by priority, not by arrival time.ArrayList allows nulls, HashSet allows one null, and ArrayDeque rejects null because null is also used as a signal for an empty poll.List interface does not guarantee fast access; LinkedList and ArrayList behave very differently.One line to remember: List = lane, Set = filter, Queue = line. Lane means ordered positions, filter means no duplicates pass through, and line means first come, first served.
Real-World Example: Imagine a checkout service in an e-commerce system. The service may keep a List of cart items because the order of items is shown to the customer, a Set of coupon codes or product IDs to avoid duplicates, and a Queue of payment retry jobs so failed payments are retried in arrival order.
What goes wrong when teams confuse these? If a developer uses a Set for cart items, two identical products collapse into one and the customer sees the wrong quantity. If they use a List where uniqueness is required, duplicate retries or duplicate notifications can be sent. If they use the wrong queue type, urgent jobs may get stuck behind old ones, or a priority-sensitive workflow may process the wrong task first.
Symptoms you would see: duplicate database writes, missing line items in the UI, retry logs showing the same order being processed twice, and support tickets saying the cart total or notification count is wrong. In production, these bugs are painful because the code still runs; it just quietly breaks business rules.
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Queue;
import java.util.Set;
public class Main {
public static void main(String[] args) {
// LIST: keep order and allow duplicates.
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("apple"); // duplicate is allowed
list.add(null); // ArrayList allows null
System.out.println("List contents: " + list);
System.out.println("List[1]: " + list.get(1));
System.out.println("List size: " + list.size());
// SET: keep only unique values.
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
set.add("apple"); // ignored because it is already present
set.add(null); // HashSet allows one null
System.out.println("Set contents: " + set);
System.out.println("Set contains 'apple': " + set.contains("apple"));
System.out.println("Set size: " + set.size());
// QUEUE: process items in arrival order.
Queue<String> queue = new ArrayDeque<>();
queue.offer("job-1");
queue.offer("job-2");
queue.offer("job-3");
System.out.println("Queue peek (no removal): " + queue.peek());
System.out.println("Queue poll (removes head): " + queue.poll());
System.out.println("Queue after poll: " + queue);
// Edge case: polling an empty queue returns null instead of throwing.
queue.poll();
queue.poll();
System.out.println("Poll on empty queue: " + queue.poll());
// Failure path: ArrayDeque rejects null because null would be ambiguous.
try {
queue.offer(null);
} catch (NullPointerException e) {
System.out.println("ArrayDeque rejects null: " + e.getClass().getSimpleName());
}
// Mini summary to reinforce the mental model.
System.out.println("\nSummary:");
System.out.println("List = ordered, duplicates allowed, index-based access");
System.out.println("Set = unique values only");
System.out.println("Queue = process in line order");
}
}
Follow-up & Tricky Questions:
HashSet, LinkedHashSet, and TreeSet? HashSet is fastest on average and does not promise order, LinkedHashSet keeps insertion order, and TreeSet keeps elements sorted using a tree, so operations are usually O(log n).ArrayDeque over LinkedList for a queue? ArrayDeque is usually faster and more memory-friendly for queue and stack-like use because it uses a resizable array instead of storing one node object per element.Queue? offer(), poll(), and peek() because they are safer: they return special values instead of throwing exceptions in common empty/full situations.HashSet need hashCode() and equals()? hashCode() helps find the bucket quickly, and equals() confirms whether two objects are truly the same value. If they do not match the contract, the set can store duplicates that should have been equal.Queue contain duplicates? Queue always mean FIFO? PriorityQueue removes the highest-priority item first, so it is a queue but not a simple first-in-first-out line.null? HashSet allows one null, but sorted sets like TreeSet typically reject null because they need to compare elements.List always fast for lookup? ArrayList is fast for index lookup, but a LinkedList is not; interface choice does not guarantee performance.Common Mistakes:
Set for ordered data. Correction: choose List if position matters, or LinkedHashSet only if you need uniqueness plus insertion order.Queue always means FIFO. Correction: check the implementation; PriorityQueue is ordered by priority.equals() and hashCode() on custom objects in a set. Correction: implement both consistently so duplicates are detected properly.ArrayList, HashSet, and ArrayDeque, because real performance comes from the implementation.Memory Hook: List = lane, Set = filter, Queue = line. Lane keeps positions, filter blocks duplicates, line processes whoever arrived first.
Cheat Sheet:
List = ordered, duplicates allowed, index access.Set = unique values only, no duplicate entries.Queue = process items in arrival order, usually with offer/poll/peek.ArrayList is great for fast reads by index.HashSet gives average O(1) membership checks.ArrayDeque is a strong default queue implementation.Practice Tasks:
List of book titles and print the third item.Set of emails and prove duplicates are removed.Queue of tasks and process them until empty, then test what happens when you poll again.