Read alongside
Dev.java: Learn Java: The Collections Framework
Collection interfaces and implementations; continue with the Type Erasure, Records and Virtual Threads tutorials listed under this resource.
Objectives
- Choose among ArrayList, ArrayDeque, HashMap, LinkedHashMap, TreeMap and PriorityQueue for a task and state the cost of the operations used.
- Implement equals and hashCode consistently, or use a record, and explain what breaks when a key is mutated after insertion into a HashMap.
- Explain type erasure and its consequences: no runtime generic type tests, no generic array creation, and the role of bounded wildcards.
- Use ExecutorService, CompletableFuture, ConcurrentHashMap and atomic classes instead of raw threads, and explain what volatile does and does not guarantee.
- Describe heap versus stack, generational garbage collection and how memory leaks arise in a garbage-collected language.
Why it matters
Choosing Java for an interview signals that you write production-style Java. The common failures are semantic rather than syntactic: a HashMap key whose hash changes after insertion, a counter made "thread-safe" with volatile, a generic method that assumes type information exists at runtime, or a cache that leaks because its entries stay reachable.
Core ideas
- Collections. Program to interfaces (
List,Map,Deque).ArrayListgives O(1) indexed access;ArrayDequeis the usual stack and queue;HashMaphas expected O(1) operations and no order;LinkedHashMapkeeps insertion or access order, which makes a simple LRU cache;TreeMapkeeps keys sorted with O(log n) operations and range queries;PriorityQueueis a binary heap ordered by natural order or a comparator. Iterators of the general-purpose implementations are fail-fast on a best-effort basis: a structural change during iteration usually throwsConcurrentModificationException. - equals and hashCode. Equal objects must have equal hash codes, and both should depend only on fields that do not change while the object sits in a hash-based collection.
==compares references, so compare boxed numbers and strings withequals. Records generate consistentequals,hashCodeandtoStringfrom their components. - Generics and erasure. Type arguments exist only at compile time; at runtime
List<String>andList<Integer>share one class. You cannot testinstanceof List<String>, createnew T[n], or overload methods that differ only in type arguments. Use? extends Tfor parameters you only read from and? super Tfor parameters you only write to. - Immutability.
finalstops reassignment of a field, not mutation of the object it refers to. Immutable classes (final fields, no setters, defensive copies, or records with immutable components) are easy to share between threads.List.ofbuilds an unmodifiable list;Collections.unmodifiableListis a read-only view of a list that can still change underneath. - Concurrency. Prefer executors to hand-managed threads,
CompletableFuturefor composing asynchronous results, andConcurrentHashMap,AtomicLongorLongAdderfor shared state. Since Java 21, virtual threads make thread-per-task code cheap for blocking I/O.volatileguarantees visibility and ordering of individual reads and writes but does not makecount++atomic;synchronizedand thejava.util.concurrentlocks provide mutual exclusion plus happens-before edges. - JVM memory. Objects live on the garbage-collected heap; each thread's stack holds frames with local primitives and references. HotSpot's collectors are generational because most objects die young, and G1 is selected by default on most configurations. A Java leak is an object that stays reachable but is no longer needed, such as entries in a static map or listeners never removed.
Common misconceptions
- "
volatilemakes increments thread-safe." Each read and write is visible, butcount++is still a read-modify-write race; use an atomic class or a lock. - "
finalmeans immutable." It fixes the reference, not the state of the referenced object. - "Generic types are checked at runtime." They are erased; raw types and unchecked casts can put a wrong element into a collection, which then fails with a ClassCastException far from the cause.
- "Garbage collection prevents memory leaks." It reclaims only unreachable objects; reachable but useless objects accumulate.
How to approach it
Write small programs that demonstrate each failure (a mutated HashMap key, a lost update under volatile) and then fix them. Mid-level and senior backend conversations may extend into thread-pool sizing, CompletableFuture error handling and garbage-collection pauses.
Self-check before you finish
- When would you choose TreeMap over HashMap?
- What goes wrong if two equal objects have different hash codes?
- Why can you not write new T[10] in a generic class?
- What does ? super T allow you to do with a parameter?
- Is a final List<String> field immutable?
- What makes an object eligible for garbage collection?