Fundamentals 21 min read

Java Interview Questions: Collections, HashMap, Concurrency, JVM Memory, GC, References, and Redis

This article compiles a set of Java interview questions covering the differences between ArrayList and LinkedList, the internal workings and resizing of HashMap, concurrency primitives like synchronized and ReentrantLock, JVM memory layout, garbage‑collection algorithms, reference types, and Redis persistence and distributed‑lock mechanisms.

IT Services Circle
IT Services Circle
IT Services Circle
Java Interview Questions: Collections, HashMap, Concurrency, JVM Memory, GC, References, and Redis

Java Interview Questions Overview

The following content collects typical Java interview questions that focus on core language features, data structures, concurrency, JVM internals, garbage collection, reference types, and Redis usage.

Difference between ArrayList and LinkedList

Underlying data structure : ArrayList uses a dynamic array, LinkedList uses a doubly‑linked list.

Random access performance : ArrayList provides O(1) index access; LinkedList requires O(n) traversal.

Insertion and deletion : ArrayList is O(1) at the tail but O(n) elsewhere; LinkedList is O(1) at any position because it only updates node pointers.

Memory consumption : LinkedList stores extra node pointers, so it typically uses more memory than ArrayList for the same number of elements.

HashMap put process and resizing mechanism

The put() method follows a multi‑step procedure:

Compute the hash and locate the bucket index.

If the bucket is empty, create a new Entry and store the key‑value pair.

If the bucket already contains entries, compare the hash and key; replace the value if the key matches.

If the key differs, traverse the bucket (linked list or red‑black tree) to find a matching key or append a new entry.

When a linked‑list bucket exceeds the threshold (default 8) and the table size is at least 64, convert the list to a red‑black tree.

Check the load factor (default 0.75); if exceeded, trigger resizing.

Resize by creating a new array of double size, re‑hashing existing entries, and updating the table reference.

Finish the insertion.

Note that both keys and values in a HashMap may be null , and the structure is not thread‑safe.

Why HashMap is not thread‑safe

In JDK 1.7, concurrent resizing could cause entry loops and data loss.

In JDK 1.8, although the red‑black tree improves performance, concurrent put may still overwrite data without proper synchronization.

Is HashMap.get() always safe?

Calling get(null) on an uninitialized map throws NullPointerException . If the map is initialized, null is a valid key.

Because HashMap is not thread‑safe, concurrent reads/writes can lead to inconsistent results or ConcurrentModificationException . Use ConcurrentHashMap for thread‑safe access.

Why ConcurrentHashMap is thread‑safe

JDK 1.7 implements it with segment locks (each segment is a ReentrantLock ) and an array of HashEntry objects. JDK 1.8 replaces segments with finer‑grained locking using volatile , CAS, and synchronized blocks, and optionally converts buckets to red‑black trees for better scalability.

Difference between synchronized and ReentrantLock

Usage : synchronized can annotate methods, static methods, or blocks; ReentrantLock works only on code blocks.

Lock acquisition/release : synchronized is automatic; ReentrantLock requires explicit lock() and unlock() .

Fairness : synchronized is non‑fair; ReentrantLock can be configured as fair or non‑fair.

Interruptibility : ReentrantLock can respond to interrupts; synchronized cannot.

Implementation : synchronized is built into the JVM monitor; ReentrantLock is built on AQS.

ReentrantLock implementation principle

The lock state is stored in AQS's state . When a thread acquires the lock, state is incremented and the owning thread is recorded. Re‑entrance increments the state again; releasing decrements it, and when it reaches zero the lock is fully released.

final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    } else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) // overflow
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

JVM Memory Structure

Program Counter : per‑thread pointer to the current bytecode instruction.

Java Virtual Machine Stack : per‑thread stack frames holding local variables, operand stack, and return addresses.

Native Method Stack : similar to the JVM stack but for native methods.

Java Heap : shared runtime memory for object allocation; divided into Young (Eden, Survivor) and Old generations.

Method Area : stores class metadata, static variables, and bytecode (PermGen in Java 8‑, Metaspace thereafter).

Garbage‑Collection Algorithms

Mark‑Sweep : marks reachable objects then sweeps unmarked ones; can cause fragmentation.

Copying : splits memory into two halves; live objects are copied to the other half during collection, eliminating fragmentation but halving usable space.

Mark‑Compact : moves live objects to one end of the heap, then compacts free space.

Generational Collection : separates objects by age (young vs. old) and applies different algorithms to each.

Reference Types in Java

Strong Reference : ordinary references; objects are not reclaimed while reachable.

Soft Reference : reclaimed only when memory is low; useful for caches.

Weak Reference : reclaimed on any GC cycle regardless of memory pressure.

Phantom Reference : used with a ReferenceQueue to perform cleanup actions before object memory is reclaimed.

Redis Persistence Mechanisms

AOF (Append‑Only File) : logs every write operation.

RDB Snapshot : periodically dumps the in‑memory dataset to a binary file.

Hybrid Persistence : combines AOF and RDB (available since Redis 4.0).

Redis Distributed Lock Implementation

Use the SET command with NX (set if not exists) and PX (expire) options to acquire a lock, and a Lua script to release it atomically.

SET lock_key unique_value NX PX 10000
// Release lock only if the stored value matches
if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

Opinion on Xiaomi Car Launch

The article briefly mentions personal thoughts on the impact of Xiaomi's car release, but no technical details are provided.

JavaJVMConcurrencyRedisInterviewHashMap
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.