Essential Java Interview Topics and Concepts

Java Primitive Types

Java supports eight primitive data types:

  • 8-bit: byte
  • 16-bit: short, char
  • 32-bit: int, float
  • 64-bit: long, double
  • boolean

Java Data Structures

Arrays

Arrays offer O(1) access time via index, making them excellent for random access operations and sequential iteration. However, their size is fixed at creation time, preventing dynamic expansion. Arrays can only hold elements of a single type, and inserting or removing elements requires shifting all subsequent elements, resulting in O(n) time complexity for modification operations.

Linked Lists

A linked list is a recursive structure where each node contains a reference to the next node along with its payload data. This structure enables efficient O(1) insertions and deletions at known positions, but accessing elements requires traversing from the head, making access O(n).

Stacks

A stack follows the Last-In-First-Out (LIFO) principle, analogous to stacking plates. Elements can only be pushed onto or popped from the top. The first element pushed becomes the bottommost, and the last element pushed becomes the topmost, making it the first to be retrieved.

Queues

A queue implements the First-In-First-Out (FIFO) principle, similar to a pipe with both ends open. The front end handles deletions (dequeue), while the rear end handles insertions (enqueue). Elements enter at the rear and exit from the front in the order they were added.

Trees

Trees represent hierarchical structures consisting of n (n>0) nodes with parent-child relationships. Key characteristics include: each node has limited children or none; the root has no parent; every non-root node has exactly one parent; and nodes can be divided into multiple non-overlapping subtrees.

Heaps

Heaps are tree-based structures implemented using arrays. They maintain a property where each node's value is always greater than or equal to (max heap) or less than or equal to (min heap) its children's values. Heaps are always complete binary trees. Max heaps have the largest element at the root, while min heaps have the smallest at the root.

Hash Tables

Hash tables provide constant-time average complexity for search, insertion, and deletion operations. They map keys to values using a hash function, enabling direct access to stored elements through their computed indices.

Graphs

Graphs consist of a finite non-empty set of vertices and a set of edges connecting pairs of vertices. They can be directed or undirected, weighted or unweighted.

String, StringBuffer, and StringBuilder

Performance ranking (fastest to slowest): StringBuilder > StringBuffer > String.

StringBuilder lacks synchronization and is not thread-safe, while StringBuffer is synchronized and thread-safe. Use String for small-scale operations, StringBuilder for single-threaded scenarios with frequent modifications, and StringBuffer for multi-threaded environments requiring frequent string manipulation.

ArrayList versus LinkedList

ArrayList and Vector use array-based implementations, wrapping internal array operations such as addition, deletion, insertion, and array resizing. LinkedList uses a doubly-linked list structure.

ArrayList provides fast random access via get() but slower insertions and deletions. LinkedList excels at insertions and deletions but suffers from slow random access. Under normal circumstances without resizing, adding elements performs equally for both. Neither is thread-safe; use CopyOnWriteArrayList or synchronized wrappers for thread safety.

HashMap versus Hashtable

Both implement the Map interface, with key differences in thread safety, synchronization, and performance.

HashMap permits null keys and values, accepts null keys (one) and values (multiple). Hashtable rejects null entirely. HashMap is unsynchronized, making it faster in single-threaded scenarios. Hashtable is synchronized and thread-safe, allowing concurrent access from multiple threads.

HashMap's iterator is fail-fast, while Hashtable's enumerator is not. Fail-fast iterators throw ConcurrentModificationException when the collection is modified during iteration (excluding the iterator's own remove method).

For complete thread safety in modern Java, use ConcurrentHashMap instead of Hashtable. Manual synchronization can be achieved via Collections.synchronizedMap(hashMap).

Processes versus Threads

A process is an independent execution unit with its own memory space, while a thread is the smallest executable unit within a process, sharing the process's memory space.

Threads incur lower overhead than processes but provide less resource isolation and protection. Processes are better suited for scenarios requiring strict resource boundaries and security. Threads excel on symmetric multiprocessing (SMP) systems where parallel execution provides maximum benefit.

Multi-threading in Java

Creating Threads

Two approaches exist at the language level: extending java.lang.Thread or implementing java.lang.Runnable. Since Java lacks multiple inheritance, implementing Runnable is preferable when inheriting from other classes.

start() versus run()

Calling start() launches a new thread that executes run(). Directly calling run() executes the method within the current thread without spawning a new thread.

Runnable versus Callable

Runnable, present since JDK 1.0, cannot return values or throw checked exceptions. Callable, added in JDK 1.5, can return values and throw exceptions. Callable returns a Future object for retrieving results.

CyclicBarrier versus CountDownLatch

Both coordinate groups of threads waiting for others. CyclicBarrier can be reused after all threads pass; CountDownLatch is single-use only.

Stopping Threads

JDK 1.0's stop(), suspend(), and resume() methods were deprecated due to deadlock risks. Modern approaches include using a volatile boolean flag to exit the run loop or interrupting tasks. Threads terminate naturally when run() or call() completes.

Exception Handling

Uncaught exceptions cause thread termination. The Thread.UncaughtExceptionHandler interface handles unexpected interruptions, with JVM calling getUncaughtExceptionHandler() and invoking the handler's uncaughtException() method.

Deadlock Prevention

Deadlock requires four conditions: mutual exclusion, hold and wait, no preemption, and circular wait. Preventing circular wait by ordering resource acquisition eliminates deadlock possibilities.

Lock Detection

The holdsLock() method in java.lang.Thread returns true if the current thread holds a specific object's lock.

wait() versus sleep()

wait() belongs to Object and releases the lock while waiting, functioning for inter-thread communication. sleep() belongs to Thread and merely suspends execution for the specified duration without releasing locks.

Controlling Execution Order

public class SequenceDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread first = new Thread(new TaskOne());
        Thread second = new Thread(new TaskTwo());
        Thread third = new Thread(new TaskThree());
        first.start();
        first.join();
        second.start();
        second.join();
        third.start();
    }
}

class TaskOne implements Runnable {
    @Override
    public void run() {
        System.out.println("Executing task 1");
    }
}

class TaskTwo implements Runnable {
    @Override
    public void run() {
        System.out.println("Executing task 2");
    }
}

class TaskThree implements Runnable {
    @Override
    public void run() {
        System.out.println("Executing task 3");
    }
}

The join() method forces the calling thread to wait for the joined thread to complete before proceeding.

public class ExecutorSequenceDemo {
    private static ExecutorService executor = Executors.newSingleThreadExecutor();

    public static void main(String[] args) {
        executor.submit(() -> System.out.println("Task 1"));
        executor.submit(() -> System.out.println("Task 2"));
        executor.submit(() -> System.out.println("Task 3"));
        executor.shutdown();
    }
}

Using newSingleThreadExecutor creates an executor with a FIFO queue ensuring sequential task execution.

IO versus NIO

The fundamental distinction is orientation: traditional IO handles streams (byte-by-byte), while NIO handles buffers (blocks of data).

Byte Streams

InputStream and OutputStream are abstract classes for byte stream operations. Subclasses like FileInputStream and FileOutputStream handle file operations.

Character Streams

InputStreamReader acts as a bridge between byte streams and character streams, converting bytes to characters. OutputStreamWriter performs the reverse conversion.

Buffered Streams

BufferedReader extends Reader, providing efficient text reading with methods like readLine(). BufferedWriter extends Writer, offering buffered text writing with newLine() for platform-specific line breaks.

Example: BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("path"), "utf8"));

Redis Data Types

Strings

Stored with SET key value. Strings are binary-safe and can contain any data, including images or serialized objects. Maximum size is 512MB per key.

Hashes

Created with HMSET name field1 value1 field2 value2. Hashes map string fields to string values, ideal for representing objects.

Lists

Ordered string collections supporting LPUSH (add to head) and RPUSH (add to tail). LPOP and RPOP remove from respective ends. LREM removes elements, LLEN returns length.

Sets

Unordered collections with SADD. Duplicates are not permitted. Operations like SADD, SREM, and membership tests execute in O(1).

Sorted Sets (ZSET)

Created with ZADD name score member. Each member has an associated score for ordering. Members are unique while scores may repeat.

Persistence

Redis offers RDB (default) and AOF persistence modes. RDB creates point-in-time snapshots, while AOF logs every write operation for durability.

Database Transactions

Transactions must satisfy ACID properties:

  • Atomicity: All operations succeed together or fail completely
  • Consistency: Database transitions between valid states
  • Isolation: Concurrent transactions don't interfere with each other
  • Durability: Committed changes survive system failures

HBase BulkLoad

BulkLoad generates HFiles through MapReduce jobs and loads them into HBase tables. This approach provides the fastest loading performance for initial data imports. If a table contains existing data, additional HFile loads trigger region splits. Output should use ImmutableBytesWritable and KeyValue pairs.

Spring MVC

Spring MVC is an open-source MVC framework combining Struts2 functionality with Spring's dependency injection. It functions as a module with in the Spring ecosystem, enabling seamless integration without additional configuration.

The architecture separates concerns:

  • Model: Business logic (services, repositories, entities)
  • View: Presentation (JSP, HTML templates)
  • Controller: Request handling and view selection

Spring IoC and AOP

Inversion of Control Container

The IoC container manages object lifecycle and dependencies. Unlike traditional instantiation where code controls object creation, IoC delegates this responsibility to the container. BeanFactory serves as the primary IoC implementation in Spring.

Dependency Injection

DI occurs after container instantiates objects, populating their dependencies. Injection approaches include setter injection, static factory method injection, constructor injection, and annotation-based configuration.

Aspect-Oriented Programming

AOP separates cross-cutting concerns from business logic. Instead of duplicating logging, transaction management, or security across multiple services, these concerns are defined once and applied transparently.

Core concepts:

  • Aspect: Shared functionality implementation (logging, security, transactions)
  • Advice: The actual code executing at specified join points
  • Joinpoint: Execution points where advice can intercede (method calls, exception throwing)
  • Pointcut: Expression defining which joinpoints receive advice
  • Target: Object receiving advice
  • Proxy: Wrapper generated around the target
  • Weaving: Process of applying advice to targets, occurring at compile, load, or runtime

Advice types: Before, AfterReturning, AfterThrowing, After, Around.

SQL Optimizaton

  • Create unique indexes for columns requiring uniqueness
  • Optimize queries by indexing columns used in WHERE and ORDER BY clauses
  • Avoid full table scans by structuring queries efficiently
  • Use SELECT INTO instead of CREATE followed by INSERT for bulk data loading
  • Minimize temporary table creation and deletion to reduce system resource consumption

MySQL versus Oracle

Aspect MySQL Oracle
Category Open-source, smaller deployments Enterprise, larger installations
Scalability Handles substantial concurrent load Optimized for high concurrency
Installation Footprint ~150MB ~3GB
Primary Key Auto-increment available Requires sequences
String Handling Double quotes acceptable Single quotes only; embedded quotes doubled
Pagination LIMIT offset, count ROWNUM with restrictions (ROWNUM < n only)
NULL Semantics Empty strings differ from NULL NOT NULL columns reject empty strings
Transaction Support Limited isolation levels Full ANSI SQL transaction semantics

Singleton Pattern

Singleton ensures a class has exactly one instance while providing global access to it. Common applications include thread pools, caches, logging systems, and hardware resource managers.

Requirements:

  1. Exactly one instance
  2. Self-instantiation
  3. Global accessibility

Factory Pattern

Factory patterns separate object creation from client code, exposing creation through a common interface.

Intent: Define an interface for object creation, letting subclasses determine which class to instantiate.

When to use: Different conditions requiring different object instantiation.

Advantages: Loose coupling, extensibility, implementation hiding.

Disadvantages: Increased system complexity and file count with each product addition.

Use cases: Logging systems (file, database, remote destinations), database abstraction layers, connection pool frameworks with multiple protocols.

Static versus Dynamic Proxies

Static proxies are compiled classes existing before runtime. Dynamic proxies are generated at runtime using reflection.

Static proxies handle single classes; dynamic proxies handle multiple implementations of an interface. Static proxies require advance knowledge of target classes; dynamic proxies discover targets during execution.

Dynamic proxies implement InvocationHandler, using Proxy.newProxyInstance() to create instances. Alternative approaches like CGLIB proxy classes without requiring interface implementation by creating subclasses at runtime.

String Comparison Methods

equals() performs case-sensitive comparison, requiring identical character sequences. equalsIgnoreCase() ignores case differences, treating 'A' through 'Z' as equivalent to 'a' through 'z'.

ehcache versus Redis

ehcache operates within the JVM with exceptional speed but limited sharing capabilities across distributed deployments. Redis communicates via socket connections, providing cross-process caching with mature clustering support.

Use ehcache for single applications or scenarios demanding minimal latency. Choose Redis for distributed systems requiring cache sharing, cross-node consistency, or large-scale data caching.

Interfaces versus Abstract Classes

Criteria Interface Abstract Class
Method defaults All abstract Mixed abstract and concrete
Inheritance Multiple interfaces Single class
Implementation requirement Must implement all methods May leave methods unimplemented
Interface implementation Can implement while keeping abstract Can implement interfaces without methods
Variable types Final only Any type
Access modifiers Public only Private, protected, or public
Instantiation Never Never (unless main method exists)

JVM Memory Architecture

Method Area

Stores class metadata (name, modifiers, constants), static variables, constructors, and method definitions. Shared across all threads, subject to garbage collection. In HotSpot, corresponds to the Permanent Generation. Contains Runtime Constant Pool for compiler-generated constants and runtime-generated values like String.intern() results.

Heap

Primary GC target, shared across all threads. Stores object instances and arrays created via new.

VM Stack

Operating-system memory allocated per thread. Contains stack frames for each method invocation, storing local variables, dynamic linking information, and method exit data. Throws StackOverflowError for deep recursion or OutOfMemoryError when expansion fails.

Native Method Stack

Supports native method execution, tracking native method call states. Similar to VM Stack but dedicated to native code rather than Java methods.

Program Counter Register

Small memory region directly within CPU, storing the current execution address per thread. For Java methods, holds the bytecode instruction address; for native methods, contains undefined values. Never throws OutOfMemoryError.

JDK, JRE, and JVM Relationships

JDK encompasses JRE plus development tools (compilers, debuggers) and core libraries. JRE provides runtime environment containing JVM implementation and core class libraries. JVM executes Java bytecode, enabling platform independence.

Method Overriding versus Overloading

Overriding replaces a parent class method's implementation in a subclass while maintaining the signature. Overloading creates multiple methods with the same name but different parameter lists within the same class.

String Constant Pool

The JVM maintains a string pool to reduce memory consumption. When creating string literals, the interpreter checks the pool first. If present, returns the existing reference; otherwise, creates a new instance and adds it to the pool. The constant pool also stores method and field references from compiled class files.

Tags: java Interview data-structures multi-threading Spring

Posted on Sat, 16 May 2026 08:47:52 +0000 by Someone789