Java Collections Interview Questions: 8 Answers with Runnable Examples

Practice eight Java Collections interview questions with runnable examples covering hashing, concurrency, iterators, ordering, queues, and collection trade-offs

Topics: Java, Collections, Data structures, Backend engineering

Author: PracHub

Published: 10/18/2026

Java Collections Interview Questions: 8 Answers with Runnable Examples

October 18, 2026
9 min read
Java Collections Interview Questions: 8 Answers with Runnable Examples

Quick Overview

Practice eight Java Collections interview questions with runnable examples covering hashing, concurrency, iterators, ordering, queues, and collection trade-offs.

JavaCollectionsData structuresBackend engineering
Software EngineerFree

Java Collections interview questions become easier when you start with the operations the program needs: lookup, indexed access, ordered traversal, priority selection, or concurrent updates. Name the interface, choose an implementation, and explain the behavior your code depends on.

These eight answers include independent, runnable examples. Save one example at a time as Example.java, then run javac Example.java and java Example. The examples use Java 17-compatible language features and APIs and were checked with a Java 21 toolchain. Each output block shows the expected result.

Oracle's Collections Framework overview is the reference for the interface hierarchy. Map belongs to the framework but does not extend Collection.

1. How do HashMap, equals, and hashCode work together?

Hashing narrows the search for a key; equality decides whether a candidate key matches. Equal keys must have equal hash codes. The reverse is not required: unequal keys may collide.

This example uses a record with a String and an int as its identity. A separately constructed equal key finds the same entry:

import java.util.HashMap;
import java.util.Map;

public class Example {
    record EmployeeKey(String department, int id) {}

    public static void main(String[] args) {
        Map<EmployeeKey, String> names = new HashMap<>();
        names.put(new EmployeeKey("Platform", 7), "Mina");
        System.out.println(names.get(new EmployeeKey("Platform", 7)));
        System.out.println(names.containsKey(new EmployeeKey("Platform", 8)));
    }
}
Mina
false

Records generate equality and hashing from their components, but they do not make referenced objects deeply immutable. Here, the String and int components avoid mutable-key state. Do not mutate identity fields after putting a key into a map: its new hash or equality can make an existing entry unreachable through ordinary lookup.

HashMap's API contract describes constant-time basic operations under suitable hash distribution, permits a null key and null values, and provides no iteration-order guarantee. Do not present an implementation's bucket thresholds as a universal Map contract. See the record reference for generated members.

Practice Explain hash collisions and Java HashMap complexity, including collision behavior and the difference between expected and worst-case costs.

2. When do you need ConcurrentHashMap rather than HashMap or Hashtable?

Use HashMap for thread-confined state or access protected by an appropriate external synchronization policy. Hashtable is a legacy synchronized map. ConcurrentHashMap supports concurrent access and atomic map operations, but separate calls do not automatically form an atomic workflow.

For example, get followed by put can lose an increment when threads interleave. Express a per-key update using merge:

import java.util.concurrent.ConcurrentHashMap;

public class Example {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> counts = new ConcurrentHashMap<>();
        counts.merge("jobs", 1, Integer::sum);
        counts.merge("jobs", 1, Integer::sum);
        System.out.println(counts.get("jobs"));
    }
}
2

This sequential example demonstrates the operation's result; it is not a concurrency test. The atomic-update guarantee comes from the ConcurrentHashMap contract. Neither it nor Hashtable permits null keys or values.

computeIfAbsent can initialize an absent mapping, but a thread-safe map does not make a mutable value thread-safe. Keep mapping functions short and avoid recursive map updates. Operations spanning several keys or external systems require a wider consistency design.

Practice Assess HashMap vs ConcurrentHashMap, then Explain Java ConcurrentHashMap and queues. Explain the required atomic boundary before discussing throughput.

3. Is LinkedList faster than ArrayList for removals?

Only after you specify how the position is found. ArrayList provides O(1) indexed access, amortized O(1) append, and O(n) middle insertion or removal because elements shift. LinkedList has O(n) indexed access; an iterator already at a position can perform a local insertion or removal without another traversal.

Also distinguish an index from a value. On a list of Integer values, the two remove overloads do different things:

import java.util.ArrayList;
import java.util.List;

public class Example {
    public static void main(String[] args) {
        List<Integer> values = new ArrayList<>(List.of(10, 20, 30));
        values.remove(1);                 // Remove the element at index 1.
        System.out.println(values);
        values.remove(Integer.valueOf(10)); // Remove the matching value.
        System.out.println(values);
    }
}
[10, 30]
[30]

Replacing the last call with remove(10) asks for index 10 and throws for this list. Likewise, choosing LinkedList does not make a loop of repeated indexed lookups efficient. For queue or stack operations, consider ArrayDeque instead of paying for linked nodes you do not need.

Use the ArrayList and LinkedList contracts to explain costs. Benchmark a real workload before claiming one implementation is universally faster.

4. What does fail-fast iteration guarantee?

Fail-fast iterators can detect structural modification outside their supported mutation operations. Detection is a debugging aid, made on a best-effort basis; it does not provide synchronization or prove that a race-free execution occurred. “Fail-safe” is informal shorthand, not a single Java API guarantee.

This example removes through an iterator, then contrasts a snapshot with the current contents:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class Example {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>(List.of("Ada", "", "Lin"));
        for (Iterator<String> it = names.iterator(); it.hasNext();) {
            if (it.next().isBlank()) {
                it.remove();
            }
        }
        System.out.println(names);

        CopyOnWriteArrayList<String> listeners = new CopyOnWriteArrayList<>(names);
        Iterator<String> snapshot = listeners.iterator();
        listeners.add("Zoe");
        List<String> seen = new ArrayList<>();
        snapshot.forEachRemaining(seen::add);
        System.out.println(seen);
        System.out.println(listeners);
    }
}
[Ada, Lin]
[Ada, Lin]
[Ada, Lin, Zoe]

The Iterator contract governs supported removal; not every iterator supports it. In particular, a CopyOnWriteArrayList snapshot iterator does not support remove. Its snapshot sees the backing array as it existed when the iterator was created, while writes copy the array.

CopyOnWriteArrayList can fit read-heavy, rarely updated listener lists. ConcurrentHashMap iterators are instead weakly consistent: they may reflect concurrent changes, without providing one fixed snapshot of the entire map. Do not describe every concurrent iterator as copying its collection.

Practice Implement iterators and write tests in Java, including exhaustion and unsupported operations.

5. When should you use Comparable versus Comparator?

Comparable gives a type a natural order through compareTo. Comparator supplies an ordering separately, which is useful for different views of the same data or a class you cannot modify.

Compose comparison fields explicitly. Avoid subtraction such as a.salary() - b.salary(): integer overflow can reverse the intended result.

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Example {
    record Employee(String name, int salary, int id) {}

    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<>(List.of(
            new Employee("Mina", 100, 2),
            new Employee("Ari", 100, 1),
            new Employee("Zoe", 90, 3)
        ));
        employees.sort(Comparator.comparingInt(Employee::salary)
            .thenComparing(Employee::name)
            .thenComparingInt(Employee::id));
        System.out.println(employees.stream().map(Employee::name).toList());
    }
}
[Zoe, Ari, Mina]

Define null handling if nulls are allowed. A comparator must be transitive and consistent in its ordering decisions; adding a tie-break field is useful only when it expresses the required order. See the Comparator contract.

Comparison returning zero has an additional meaning in sorted sets and maps: it determines whether elements or keys count as the same. That makes an apparently harmless comparator a possible data-loss bug, as the next example shows.

6. How do HashSet, LinkedHashSet, and TreeSet define duplicates and order?

HashSet uses hashing and equality, with no iteration-order guarantee. LinkedHashSet preserves insertion order for ordinary add operations while removing duplicates. TreeSet maintains comparison order and uses comparison returning zero to determine membership.

import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class Example {
    public static void main(String[] args) {
        Set<String> encounterOrder = new LinkedHashSet<>(
            List.of("pear", "fig", "pear", "plum"));
        System.out.println(encounterOrder);

        Set<String> byLength = new TreeSet<>(Comparator.comparingInt(String::length));
        byLength.addAll(List.of("aa", "bb", "c"));
        System.out.println(byLength.size());
        System.out.println(byLength.contains("zz"));
    }
}
[pear, fig, plum]
2
true

The length-only comparator treats aa, bb, and even the lookup value zz as equivalent. This may fit “one representative per length,” but it does not implement ordinary String equality. If distinct strings must remain distinct, add a natural-order tie-breaker or choose another structure.

TreeSet's documentation explains the equality consistency requirement for obeying the general Set contract and O(log n) basic operations. Hash-based set operations are expected O(1) under suitable hashing. Pay for sorted order when you need ordered traversal or navigation, not because “sorted” sounds better.

7. Why choose ArrayDeque for a stack or queue?

ArrayDeque supports efficient operations at both ends without LinkedList's per-node links. Stack is a legacy class; the Deque interface expresses the usual stack operations directly. ArrayDeque rejects null elements and does not make unsynchronized concurrent access safe.

import java.util.ArrayDeque;
import java.util.Deque;

public class Example {
    public static void main(String[] args) {
        Deque<String> stack = new ArrayDeque<>();
        stack.push("first");
        stack.push("second");
        System.out.println(stack.pop());
        System.out.println(stack.poll());
        System.out.println(stack.poll());

        Deque<String> queue = new ArrayDeque<>();
        queue.offer("first");
        queue.offer("second");
        System.out.println(queue.poll());
    }
}
second
first
null
first

push and pop give last-in, first-out behavior; offer and poll give first-in, first-out behavior here. Empty poll returns null, whereas empty pop throws. These distinctions matter when null is used to signal absence.

The ArrayDeque API documents amortized constant-time behavior for most end operations; searching or removing an arbitrary matching element is different work. A queue is useful for BFS, while a deque can also support sliding-window algorithms. Connect the choice to a specific operation rather than memorizing a collection name.

8. How is PriorityQueue different from TreeMap?

A PriorityQueue exposes the next element by priority, not a fully sorted iterator. Its default head is the least element. TreeMap stores key-value pairs with ordered keys and supports navigation queries such as the greatest key at or below a target.

import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.TreeMap;

public class Example {
    public static void main(String[] args) {
        PriorityQueue<Integer> priorities = new PriorityQueue<>(List.of(5, 1, 3));
        List<Integer> processed = new ArrayList<>();
        while (!priorities.isEmpty()) {
            processed.add(priorities.poll());
        }
        System.out.println(processed);

        TreeMap<Integer, String> schedule = new TreeMap<>();
        schedule.put(10, "warmup");
        schedule.put(20, "run");
        System.out.println(schedule.floorEntry(12));
    }
}
[1, 3, 5]
10=warmup

The sorted list comes from repeated removal, not from iterating the heap. PriorityQueue provides O(1) peek and O(log n) offer/poll; searching for an arbitrary value is O(n). Equal-priority elements need an explicit comparator tie-breaker if their processing order matters.

TreeMap provides O(log n) key lookup and updates. floorEntry returns null when no key qualifies. Use it for ordered key lookup or range navigation; choose a priority queue when repeatedly selecting the next item is the central operation.

Compare the requirement before naming the implementation

Required behaviorCandidateQuestion to resolve
Key lookup in thread-confined codeHashMapAre keys stable and hashes suitable?
Concurrent per-key updatesConcurrentHashMapDoes one atomic method cover the whole operation?
Repeated indexed readsArrayListHow often do middle edits occur?
Stable iteration snapshot with rare writesCopyOnWriteArrayListIs copying on writes acceptable?
Deduplication in encounter orderLinkedHashSetIs insertion order the intended order?
Sorted membership or range navigationTreeSet / TreeMapIs comparison consistent with required identity?
Single-threaded stack or queueArrayDequeShould an empty operation throw or return null?
Repeated next-priority selectionPriorityQueueAre ties defined, and is ordered iteration needed?

For backend applications, continue with Spring Boot interview questions and explain where shared state lives, who owns synchronization, and how it is tested. To apply these structures to algorithms, use the coding-pattern analysis as a starting point for targeted practice.

For newer API context, the Java 25 Collections overview and Java 27 sequenced-collections guide describe their respective releases. Check the actual target JDK before using newer APIs; the runnable examples above do not require sequenced-collection methods.

Keep practicing


Comments (0)