☕ JAVA SDE
COMPLETE DEVELOPER NOTES
FOR FRESHERS | JOB-READY EDITION
Core Java • OOP • Collections • DSA • Multithreading • JDBC • Spring Boot
Topics Covered
# Topic
1 Java Fundamentals & Setup
2 OOP — Object-Oriented Programming
3 Core Java — Strings, Arrays, Control Flow
4 Exception Handling
5 Collections Framework
6 Generics
7 File I/O & Serialization
8 Multithreading & Concurrency
9 Java 8+ Features (Lambdas, Streams, Optional)
10 Data Structures & Algorithms (DSA)
11 JDBC — Database Connectivity
12 Spring Boot Essentials
13 REST API Development
14 Design Patterns
15 Interview Q&A Cheat Sheet
2024 Edition • Freshers & Entry-Level SDEs
CHAPTER 1: Java Fundamentals & Setup
1.1 What is Java?
Java is a high-level, object-oriented, platform-independent programming language created by James Gosling at
Sun Microsystems in 1995. It follows the Write Once, Run Anywhere (WORA) principle.
Feature Description Example
Platform Independent Compiled to bytecode, runs on JVM .class file runs anywhere JVM exists
Object-Oriented Everything is an object (except Classes, Objects, Inheritance
primitives)
Strongly Typed Variable types declared at compile time int x = 5; not x = 5
Automatic Memory Garbage Collector reclaims unused No manual free() like C/C++
Mgmt memory
Multi-threaded Built-in support for concurrent Thread, Runnable, ExecutorService
programming
Secure No pointers, bytecode verification Java SecurityManager
1.2 JDK vs JRE vs JVM
JDK (Java Development Kit) ⊃ JRE (Java Runtime Environment) ⊃ JVM (Java Virtual Machine)
Component Full Form Purpose
JVM Java Virtual Machine Executes bytecode. Platform-specific.
Memory mgmt, garbage collection.
JRE Java Runtime Environment JVM + core libraries. Used to run Java
apps (not compile).
JDK Java Development Kit JRE + compiler (javac) + tools. Used to
develop Java apps.
1.3 How Java Code Runs
1. Write source code → [Link]
2. Compile: javac [Link] → generates [Link] (bytecode)
3. Run: java MyClass → JVM loads and executes the .class file
1.4 First Java Program
// File: [Link]
public class HelloWorld {
public static void main(String[] args) {
[Link]("Hello, World!");
}
}
Key Points:
• public class name must match filename exactly. • main() is the entry point — JVM calls this method. •
static means no object needed to call main. • [Link]() prints to console with a newline.
1.5 Data Types
Primitive Data Types (8 types)
Type Size | Default | Range / Use
byte 1 byte | 0 | -128 to 127
short 2 bytes | 0 | -32,768 to 32,767
int 4 bytes | 0 | -2^31 to 2^31-1 (most common)
long 8 bytes | 0L | -2^63 to 2^63-1 (use L suffix: 100L)
float 4 bytes | 0.0f | Decimal (use f suffix: 3.14f)
double 8 bytes | 0.0 | Decimal more precision (default for decimals)
char 2 bytes | '\u0000' | Single character: 'A', '1', '@'
boolean 1 bit | false | true or false only
Reference Data Types
• String, Arrays, Classes, Interfaces, Enums
• Store references (addresses) to objects on the Heap
• Default value is null
1.6 Variables & Constants
int age = 25; // local variable
String name = "Ravi"; // reference variable
final double PI = 3.14159; // constant (cannot be changed)
var list = new ArrayList<>(); // type inferred (Java 10+)
1.7 Type Casting
Widening (Implicit — automatic, no data loss)
int i = 100;
long l = i; // int -> long (auto)
double d = l; // long -> double (auto)
Narrowing (Explicit — manual, possible data loss)
double d = 9.99;
int i = (int) d; // i = 9, decimal part lost
1.8 Operators
Category Operators Example
Arithmetic + - * / % ++ -- 5 + 3 = 8, 10 % 3 = 1
Relational == != > < >= <= 5 > 3 → true
Logical && || ! true && false → false
Bitwise & | ^ ~ << >> 5&3=1
Assignment = += -= *= /= %= x += 5 same as x = x+5
Ternary condition ? val1 : val2 int max = a>b ? a : b
instanceof obj instanceof ClassName str instanceof String → true
1.9 Control Flow Statements
if-else
if (score >= 90) {
[Link]("A Grade");
} else if (score >= 70) {
[Link]("B Grade");
} else {
[Link]("C Grade");
}
switch
switch (day) {
case "MON": [Link]("Monday"); break;
case "TUE": [Link]("Tuesday"); break;
default: [Link]("Other");
}
// Switch Expression (Java 14+) — cleaner syntax
String result = switch (day) {
case "MON" -> "Monday";
case "TUE" -> "Tuesday";
default -> "Other";
};
Loops
// for loop
for (int i = 0; i < 5; i++) { [Link](i); }
// while loop
int i = 0;
while (i < 5) { [Link](i++); }
// do-while — executes at least once
do { [Link](i++); } while (i < 5);
// Enhanced for (for-each) — for arrays/collections
int[] arr = {1, 2, 3};
for (int num : arr) { [Link](num); }
1.10 Arrays
// 1D Array
int[] arr = new int[5]; // declaration
int[] arr = {10, 20, 30, 40}; // initialization
arr[0] = 100; // access/modify
[Link]([Link]); // length property
// 2D Array
int[][] matrix = new int[3][3];
int[][] matrix = {{1,2,3}, {4,5,6}, {7,8,9}};
// Useful Array Methods ([Link])
[Link](arr); // sort ascending
[Link](arr, 20); // binary search
[Link](arr, 0); // fill with value
[Link](arr, 6); // copy with new length
[Link](arr); // to string [10, 20, 30]
CHAPTER 2: Object-Oriented Programming (OOP)
OOP has 4 pillars: Encapsulation, Inheritance, Polymorphism, Abstraction. These are the MOST asked
interview topics.
2.1 Classes & Objects
Class — Blueprint
public class Student {
// Fields (instance variables)
private String name;
private int age;
private double gpa;
// Constructor
public Student(String name, int age, double gpa) {
[Link] = name; // 'this' refers to current object
[Link] = age;
[Link] = gpa;
}
// Default constructor
public Student() { this("Unknown", 0, 0.0); } // constructor chaining
// Getters & Setters
public String getName() { return name; }
public void setName(String name) { [Link] = name; }
// Method
public String toString() {
return "Student{name='" + name + "', age=" + age + "}";
}
}
Object — Instance of a Class
Student s1 = new Student("Ravi", 21, 8.5);
Student s2 = new Student(); // default constructor
[Link](s1); // calls toString()
[Link]("Raj");
2.2 Encapsulation
Wrapping data (fields) and methods together. Use private fields + public getters/setters. This protects data from
unauthorized access.
WHY it matters in interviews:
Encapsulation allows you to validate data before setting it (e.g., age can't be negative), hide internal
implementation, and change implementation without affecting users of the class.
public class BankAccount {
private double balance; // hidden
public void deposit(double amount) {
if (amount > 0) balance += amount; // validation
}
public double getBalance() { return balance; } // controlled access
}
2.3 Inheritance
A child class inherits fields and methods from a parent class using the 'extends' keyword. Promotes code
reusability.
// Parent class
public class Animal {
String name;
public void eat() { [Link](name + " is eating"); }
public void sleep() { [Link](name + " is sleeping"); }
}
// Child class inherits from Animal
public class Dog extends Animal {
public void bark() { [Link]("Woof!"); }
@Override
public void eat() { // Overriding parent method
[Link](name + " is eating dog food");
}
}
// Usage
Dog dog = new Dog();
[Link] = "Bruno";
[Link](); // calls Dog's eat (overridden)
[Link](); // calls Animal's sleep (inherited)
[Link](); // Dog's own method
super keyword
class Dog extends Animal {
Dog(String name) {
super(name); // calls Animal's constructor
}
void eat() {
[Link](); // calls parent's eat()
[Link]("...with treats!");
}
}
Important:
Java supports SINGLE inheritance (one parent only). For multiple inheritance, use Interfaces.
2.4 Polymorphism
1. Compile-time Polymorphism — Method Overloading
Same method name, different parameters (type or count). Resolved at compile time.
class Calculator {
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
int add(int a, int b, int c) { return a + b + c; }
}
// Calling
[Link](2, 3); // calls first method
[Link](2.0, 3.5); // calls second method
2. Runtime Polymorphism — Method Overriding
Child class overrides parent's method. Resolved at runtime via dynamic dispatch.
Animal a = new Dog(); // parent reference, child object
[Link](); // calls Dog's eat() at RUNTIME — polymorphism!
// Works for any Animal subtype
Animal[] animals = { new Dog(), new Cat(), new Bird() };
for (Animal animal : animals) {
[Link](); // each calls its own eat() dynamically
}
2.5 Abstraction
Abstract Class
Cannot be instantiated. May have abstract (unimplemented) and concrete (implemented) methods.
abstract class Shape {
String color;
abstract double area(); // must be implemented by subclass
void display() { // concrete method
[Link]("Area: " + area());
}
}
class Circle extends Shape {
double radius;
Circle(double r) { [Link] = r; }
@Override
double area() { return [Link] * radius * radius; }
}
Interface
100% abstraction (before Java 8). All methods are implicitly public and abstract. A class can implement multiple
interfaces.
interface Flyable {
void fly(); // abstract (implicit)
default void land() { // default method (Java 8+)
[Link]("Landing...");
}
static void rules() { // static method (Java 8+)
[Link]("Follow aviation rules");
}
}
interface Swimmable { void swim(); }
// Class implements multiple interfaces
class Duck extends Animal implements Flyable, Swimmable {
public void fly() { [Link]("Duck flying"); }
public void swim() { [Link]("Duck swimming"); }
}
Abstract Class Interface
Can have constructor No constructor
Can have instance fields Only constants (public static final)
Single inheritance (extends) Multiple implementation (implements)
Can have any access modifier Methods are public by default
Use when: shared base with Use when: define a contract/capability
partial impl
2.6 Access Modifiers
Modifier Accessible From
private Same class only
default (no keyword) Same package only
protected Same package + subclasses anywhere
public Everywhere
2.7 Static Keyword
class Counter {
static int count = 0; // shared across ALL instances
int id;
Counter() {
count++; // increments shared counter
[Link] = count;
}
static int getCount() { return count; } // static method
}
Counter c1 = new Counter(); // count = 1
Counter c2 = new Counter(); // count = 2
[Link]([Link]()); // 2, call via class name
Static Block — runs once when class loads
class Config {
static String dbUrl;
static {
// Runs when class is first loaded
dbUrl = "jdbc:mysql://localhost/mydb";
[Link]("Config initialized");
}
}
2.8 final Keyword
final int MAX = 100; // constant — cannot be reassigned
final class String { ... } // cannot be subclassed (String is final!)
class Parent {
final void show() { ... } // cannot be overridden in subclass
}
2.9 Object Class Methods
Every class in Java implicitly extends [Link]. Key methods to override:
Method Purpose & When to Override
toString() Returns string representation. Override for meaningful output.
equals(Object o) Checks logical equality. Override when you define what 'equal' means.
hashCode() Returns hash code. MUST override when equals() is overridden.
clone() Creates a copy. Override + implement Cloneable.
finalize() Called before GC. Deprecated in Java 9+.
class Point {
int x, y;
Point(int x, int y) { this.x = x; this.y = y; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Point)) return false;
Point p = (Point) o;
return x == p.x && y == p.y;
}
@Override
public int hashCode() { return [Link](x, y); }
@Override
public String toString() { return "(" + x + ", " + y + ")"; }
}
CHAPTER 3: Strings & String Manipulation
3.1 String in Java
Strings are immutable objects in Java — once created, they cannot be changed. Stored in the String Pool (part of
heap).
String s1 = "Hello"; // String literal — stored in pool
String s2 = new String("Hello"); // new object — in heap (not pool)
s1 == s2; // false (different references)
[Link](s2); // TRUE (same content) — ALWAYS use equals()
s1 = s1 + " World"; // creates a NEW string — s1 was not modified!
Common Interview Trap:
Using == to compare Strings compares references, not content. Always use .equals()
or .equalsIgnoreCase() for string comparison.
3.2 Important String Methods
Method Description Example
length() Number of characters "Hello".length() → 5
charAt(i) Character at index "Hello".charAt(1) → 'e'
substring(s, e) Extract part "Hello".substring(1,3) → "el"
indexOf(s) First occurrence index "Hello".indexOf("l") → 2
contains(s) Check if contains "Hello".contains("ell") → true
startsWith(s) Starts with prefix "Hello".startsWith("He") → true
endsWith(s) Ends with suffix "Hello".endsWith("lo") → true
toUpperCase() All uppercase "hello".toUpperCase() → "HELLO"
toLowerCase() All lowercase "HELLO".toLowerCase() → "hello"
trim() Remove whitespace " hi ".trim() → "hi"
strip() Remove whitespace (Unicode) Java 11+, better than trim()
replace(o, n) Replace occurrences "aabb".replace("aa","x") → "xbb"
split(regex) Split to array "a,b,c".split(",") → ["a","b","c"]
isEmpty() Check if empty " ".isEmpty() → false
isBlank() Check if blank " ".isBlank() → true (Java 11+)
valueOf(x) Convert to String [Link](42) → "42"
toCharArray() Convert to char[] "Hello".toCharArray()
matches(regex) Regex match "abc".matches("[a-z]+") → true
join(delim, ...) Join strings [Link]("-","a","b") → "a-b"
format(fmt, ...) Formatted string [Link]("%s is %d", "age", 5)
3.3 StringBuilder vs StringBuffer
Feature StringBuilder vs StringBuffer
Mutability Both mutable (can modify content)
Thread Safety StringBuffer is synchronized (thread-safe), StringBuilder is NOT
Performance StringBuilder is faster (no sync overhead)
Use when Use StringBuilder in single-threaded code (almost always)
StringBuilder sb = new StringBuilder();
[Link]("Hello");
[Link](" World");
[Link](5, ","); // "Hello, World"
[Link](5, 6); // remove comma
[Link](); // reverse the string
[Link](0, 5, "Hi"); // replace range
String result = [Link]();
// When to use StringBuilder:
// Concatenating strings in a loop (avoids creating N temporary objects)
StringBuilder s = new StringBuilder();
for (int i = 0; i < 1000; i++) {
[Link](i).append(','); // GOOD — one object
// DON'T do: str += i; // BAD — creates 1000 String objects
}
3.4 String Pool & Immutability
String a = "Java"; // stored in pool
String b = "Java"; // reuses same pool object
a == b; // TRUE — same reference from pool
String c = new String("Java"); // new heap object
a == c; // FALSE — different object
[Link](c); // TRUE — same content
// intern() — puts string in pool and returns pool reference
String d = [Link]();
a == d; // TRUE — now d points to pool string
3.5 Common String Programs (Interview Favorites)
Reverse a String
String reverse(String s) {
return new StringBuilder(s).reverse().toString();
}
Check Palindrome
boolean isPalindrome(String s) {
String rev = new StringBuilder(s).reverse().toString();
return [Link](rev);
}
Count occurrences of a character
long count = [Link]().filter(c -> c == 'a').count(); // Java 8 streams
Check Anagram
boolean isAnagram(String s1, String s2) {
char[] a = [Link](); [Link](a);
char[] b = [Link](); [Link](b);
return [Link](a, b);
}
CHAPTER 4: Exception Handling
4.1 Exception Hierarchy
Throwable → Error (JVM issues, don't catch) | Exception → Checked & Unchecked (RuntimeException)
Type Description & Examples
Checked Exception Must be handled at compile time. IOException, SQLException,
FileNotFoundException, ClassNotFoundException
Unchecked (RuntimeException) Occurs at runtime. NullPointerException,
ArrayIndexOutOfBoundsException, ClassCastException,
ArithmeticException, IllegalArgumentException,
NumberFormatException, StackOverflowError
Error JVM-level, usually unrecoverable. OutOfMemoryError,
StackOverflowError — DON'T catch these.
4.2 try-catch-finally
try {
int result = 10 / 0; // throws ArithmeticException
String s = null;
[Link](); // throws NullPointerException
} catch (ArithmeticException e) {
[Link]("Math error: " + [Link]());
} catch (NullPointerException e) {
[Link]("Null error: " + [Link]());
} catch (Exception e) { // catches all remaining exceptions
[Link]("Error: " + [Link]());
} finally {
[Link]("Always runs — even if exception or return!");
// Use for cleanup: close DB connections, files, etc.
}
4.3 throw vs throws
// throws — declares that method may throw exception
public void readFile(String path) throws IOException {
FileReader fr = new FileReader(path); // may throw IOException
}
// throw — actually throws an exception
public void setAge(int age) {
if (age < 0 || age > 150) {
throw new IllegalArgumentException("Invalid age: " + age);
}
[Link] = age;
}
4.4 Custom Exception
// Custom checked exception
class InsufficientFundsException extends Exception {
private double amount;
InsufficientFundsException(double amount) {
super("Insufficient funds. Need: " + amount);
[Link] = amount;
}
double getAmount() { return amount; }
}
// Usage
class BankAccount {
double balance = 1000;
void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) throw new InsufficientFundsException(amount -
balance);
balance -= amount;
}
}
4.5 try-with-resources (Java 7+)
Automatically closes resources that implement AutoCloseable. No need for finally block.
// Old way — must close manually in finally
BufferedReader br = null;
try { br = new BufferedReader(new FileReader("[Link]")); }
finally { if (br != null) [Link](); }
// New way — auto-closed at end of try block
try (BufferedReader br = new BufferedReader(new FileReader("[Link]"))) {
String line = [Link]();
} catch (IOException e) {
[Link]();
} // br is automatically closed here
4.6 Multi-catch (Java 7+)
try {
// code that may throw multiple exceptions
} catch (IOException | SQLException e) { // catch multiple types
[Link]("IO or DB error: " + [Link]());
}
CHAPTER 5: Collections Framework
Collections Framework provides ready-made data structures. Package: [Link].* Hierarchy: Iterable →
Collection → List/Set/Queue → Implementations
5.1 List — Ordered, Allows Duplicates
ArrayList — Dynamic array, fast random access
List<String> list = new ArrayList<>();
[Link]("Java"); // add at end
[Link](0, "Python"); // add at index 0
[Link](0); // O(1) random access
[Link](0); // remove by index — O(n) shift
[Link]("Java"); // remove by object
[Link](); // number of elements
[Link]("Java"); // true/false
[Link]("Java"); // index of first occurrence
[Link](0, "C++"); // replace at index
[Link](); // true if no elements
[Link](list); // sort
[Link](list); // reverse
[Link](1, 3); // view from index 1 to 2
[Link](); // convert to array
LinkedList — Doubly linked list, fast insert/delete at ends
LinkedList<Integer> ll = new LinkedList<>();
[Link](1); [Link](3); [Link](1, 2);
[Link](); [Link]();
[Link](); [Link](); // look without removing
// Also implements Queue and Deque interfaces
ArrayList vs LinkedList Use Case
ArrayList: O(1) get, O(n) Use when frequent access by index
insert/delete in middle
LinkedList: O(n) get, O(1) Use when frequent add/remove from ends
insert/delete at ends
5.2 Set — No Duplicates
HashSet — No order, O(1) operations
Set<String> set = new HashSet<>();
[Link]("Apple"); [Link]("Banana"); [Link]("Apple"); // duplicate ignored
[Link](); // 2
[Link]("Apple"); // true
[Link]("Banana");
// Iterate
for (String s : set) [Link](s); // order not guaranteed
LinkedHashSet — Maintains insertion order
TreeSet — Sorted (natural or custom order), O(log n)
TreeSet<Integer> ts = new TreeSet<>();
[Link](5); [Link](1); [Link](3); [Link](2);
// Iteration gives: 1 2 3 5 (sorted!)
[Link](); // 1, [Link](); // 5
[Link](3); // {1, 2} (elements < 3)
[Link](3); // {3, 5} (elements >= 3)
5.3 Map — Key-Value Pairs
HashMap — No order, O(1) average, allows null key
Map<String, Integer> map = new HashMap<>();
[Link]("Alice", 90); // add entry
[Link]("Alice"); // 90 — get value by key
[Link]("Bob", 0); // 0 if key not found
[Link]("Alice"); // true
[Link](90); // true
[Link]("Alice"); // remove entry
[Link](); // number of entries
[Link]("Alice", 95); // updates existing key
[Link]("Bob", 85); // only puts if key absent
// Iterate over map
for ([Link]<String,Integer> entry : [Link]()) {
[Link]([Link]() + " = " + [Link]());
}
[Link](); // Set of keys
[Link](); // Collection of values
// Java 8 - merge / compute
[Link]("Alice", 5, Integer::sum); // adds 5 to Alice's value
[Link]("Alice", (k, v) -> v == null ? 1 : v + 1);
LinkedHashMap — Maintains insertion order
TreeMap — Sorted by key, O(log n)
Hashtable — Legacy, thread-safe (use ConcurrentHashMap instead)
5.4 Queue & Deque
// Queue (FIFO)
Queue<Integer> q = new LinkedList<>();
[Link](1); [Link](2); [Link](3); // enqueue
[Link](); // 1 — dequeue (null if empty)
[Link](); // 2 — look without removing
// PriorityQueue — min-heap by default
PriorityQueue<Integer> pq = new PriorityQueue<>();
[Link](5); [Link](1); [Link](3);
[Link](); // 1 (smallest always comes out first)
// Max-heap using Comparator
PriorityQueue<Integer> maxPQ = new PriorityQueue<>([Link]());
// Deque (Double-ended queue, works as Stack too)
Deque<Integer> deque = new ArrayDeque<>();
[Link](1); [Link](2);
[Link](); [Link]();
[Link](1); [Link](); // Stack operations
5.5 Collections Utility Class
[Link](list);
[Link](list, [Link]()); // reverse sort
[Link](list);
[Link](list);
[Link](list); [Link](list);
[Link](list, "Java"); // count occurrences
[Link](list); // read-only view
[Link](list); // thread-safe wrapper
[Link](list, "Java"); // must be sorted first
[Link](5, "Hello"); // List of 5 "Hello"
5.6 Comparable vs Comparator
Comparable — Natural ordering (implement in the class itself)
class Student implements Comparable<Student> {
String name; int marks;
@Override
public int compareTo(Student other) {
return [Link] - [Link]; // ascending by marks
}
}
[Link](students); // uses compareTo()
Comparator — Custom ordering (defined externally)
// Sort by name
[Link]([Link](s -> [Link]));
// Sort by marks descending, then name ascending
[Link]([Link]((Student s) -> [Link])
.reversed().thenComparing(s -> [Link]));
CHAPTER 6: Multithreading & Concurrency
6.1 Creating Threads
Method 1 — Extend Thread class
class MyThread extends Thread {
@Override
public void run() {
[Link]("Thread: " + [Link]().getName());
}
}
MyThread t = new MyThread();
[Link](); // DO NOT call run() directly — that's not a new thread!
Method 2 — Implement Runnable (preferred)
Runnable task = () -> [Link]("Running: " +
[Link]().getName());
Thread t = new Thread(task);
[Link]();
// Or with lambda directly
new Thread(() -> [Link]("Hello from thread")).start();
6.2 Thread Lifecycle
NEW → RUNNABLE → (WAITING/BLOCKED/TIMED_WAITING) → RUNNABLE → TERMINATED
State Description
NEW Thread created but start() not called yet
RUNNABLE Thread ready to run or running (OS schedules)
BLOCKED Waiting to acquire a synchronized lock
WAITING Waiting indefinitely (wait(), join())
TIMED_WAITING Waiting for a time period (sleep(ms), wait(ms))
TERMINATED Thread finished execution
6.3 Thread Methods
Thread t = new Thread(task);
[Link](); // start new thread
[Link](); // wait for this thread to finish
[Link](1000); // wait at most 1 second
[Link](2000); // pause current thread 2 seconds
[Link](); // reference to current thread
[Link](); [Link]("WorkerThread");
[Link](); [Link](Thread.MAX_PRIORITY); // 1-10
[Link](); // true if thread is running
[Link](); // request thread interruption
[Link](); // hint to scheduler: let others run
[Link](true); // daemon thread — dies when main thread dies
6.4 Synchronization
When multiple threads access shared data, synchronization prevents data corruption (race conditions).
synchronized method
class Counter {
private int count = 0;
public synchronized void increment() {
count++; // only one thread can execute this at a time
}
public synchronized int getCount() { return count; }
}
synchronized block — more granular control
public void addItem(String item) {
// unsynchronized code here
synchronized(this) { // lock on 'this' object
[Link](item); // only this block is locked
}
// unsynchronized code here
}
6.5 Executor Framework (Java 5+)
Better than creating threads manually. Manages thread pools.
// Fixed thread pool — reuses N threads
ExecutorService executor = [Link](4);
[Link](() -> [Link]("Task running"));
[Link](callable); // returns Future
[Link](); // graceful shutdown (waits for tasks)
[Link](); // immediate shutdown
// Single thread executor
ExecutorService single = [Link]();
// Cached thread pool — creates threads as needed
ExecutorService cached = [Link]();
// Future — get result of async task
Future<Integer> future = [Link](() -> { return 42; });
int result = [Link](); // blocks until result ready
[Link]();
6.6 Callable vs Runnable
Runnable Callable<V>
void run() V call() throws Exception
No return value Returns a value (via Future)
Cannot throw checked exceptions Can throw checked exceptions
Use for fire-and-forget tasks Use when you need the result
6.7 Volatile Keyword
class SharedState {
volatile boolean running = true; // visible to all threads immediately
}
// Without volatile, threads may cache the value locally
// volatile ensures reads/writes go directly to main memory
6.8 Concurrent Collections
Class Purpose
ConcurrentHashMap Thread-safe HashMap, better than Hashtable/synchronizedMap
CopyOnWriteArrayList Thread-safe List, great for read-heavy, rare-write scenarios
BlockingQueue Queue with blocking put/take — used in producer-consumer pattern
ArrayBlockingQueue Bounded blocking queue with fixed capacity
AtomicInteger/Long Thread-safe integer operations without synchronization
AtomicInteger counter = new AtomicInteger(0);
[Link](); // thread-safe increment
[Link](5); // add 5 atomically
[Link](5, 10); // CAS operation
CHAPTER 7: Java 8+ Features (Lambda, Streams,
Optional)
Java 8 (2014) revolutionized Java with functional programming. This is heavily tested in interviews!
7.1 Lambda Expressions
A lambda is an anonymous function — shorthand for implementing a single-method (functional) interface.
// Before Java 8 — Anonymous class
Runnable r = new Runnable() { public void run() { [Link]("Hi"); } };
// Java 8 Lambda — much cleaner!
Runnable r = () -> [Link]("Hi");
// Lambda syntax
// () -> expression — no params, single expression
// (x) -> x * 2 — one param
// (x, y) -> x + y — two params
// (x, y) -> { ... return z; } — block body
// With functional interfaces
Comparator<String> comp = (a, b) -> [Link](b);
Predicate<Integer> isEven = n -> n % 2 == 0;
Function<String, Integer> length = s -> [Link]();
Consumer<String> print = s -> [Link](s);
Supplier<String> greet = () -> "Hello!";
7.2 Built-in Functional Interfaces
Interface Method & Use
Predicate<T> boolean test(T t) — condition check. filter()
Function<T,R> R apply(T t) — transform T to R. map()
Consumer<T> void accept(T t) — consume/use value. forEach()
Supplier<T> T get() — provide a value. lazy init
BiFunction<T,U,R> R apply(T t, U u) — two inputs, one output
UnaryOperator<T> T apply(T t) — Function where T=R. replaceAll()
BinaryOperator<T> T apply(T t1, T t2) — BiFunction where T=U=R. reduce()
7.3 Method References
// Four types of method references
// 1. Static method reference
Function<String, Integer> parseInt = Integer::parseInt;
// 2. Instance method on specific object
String prefix = "Hello ";
Function<String, String> greet = prefix::concat;
// 3. Instance method on arbitrary object of that type
Comparator<String> comp = String::compareToIgnoreCase;
// 4. Constructor reference
Supplier<ArrayList<String>> listFactory = ArrayList::new;
// Common use in streams
[Link]([Link]::println); // instead of s -> [Link](s)
[Link]().map(String::toUpperCase);
7.4 Stream API
Streams allow functional-style operations on collections. They are lazy (computed on demand) and can be
parallelized easily.
Stream Pipeline: Source → Intermediate Operations → Terminal Operation
List<String> names = [Link]("Ravi", "Raj", "Priya", "Rita", "Sam");
// Count names starting with 'R' with length > 3
long count = [Link]() // source
.filter(n -> [Link]("R")) // intermediate
.filter(n -> [Link]() > 3) // intermediate
.count(); // terminal
// Get sorted unique uppercase names as List
List<String> result = [Link]()
.map(String::toUpperCase) // transform each element
.distinct() // remove duplicates
.sorted() // sort alphabetically
.collect([Link]()); // collect to List
// Sum of squares of even numbers
int sum = [Link](1, 10) // 1 to 10
.filter(n -> n % 2 == 0) // keep evens
.map(n -> n * n) // square each
.sum(); // sum all
Important Stream Intermediate Operations
Operation Description & Example
filter(Predicate) Keep elements matching condition. .filter(s -> [Link]() > 3)
map(Function) Transform each element. .map(String::toUpperCase)
flatMap(Function) Flatten nested streams. .flatMap(List::stream)
distinct() Remove duplicate elements
sorted() Sort (natural order). sorted([Link]())
limit(n) Take first n elements
skip(n) Skip first n elements
peek(Consumer) For debugging — see elements without consuming
Important Stream Terminal Operations
Operation Description & Example
collect(Collector) Collect to List/Set/Map. [Link](), toSet(), groupingBy()
count() Count elements
findFirst() First element as Optional
findAny() Any element (parallel-friendly)
anyMatch(Pred) true if any element matches
allMatch(Pred) true if ALL elements match
noneMatch(Pred) true if NO elements match
min/max(Comp) Min/max element as Optional
reduce(identity, BinOp) Reduce to single value. .reduce(0, Integer::sum)
forEach(Consumer) Execute for each element
toArray() Collect to array
Collectors (Collectors.*)
// Group by first character
Map<Character, List<String>> grouped = [Link]()
.collect([Link](s -> [Link](0)));
// Join with delimiter
String joined = [Link]().collect([Link](", ", "[", "]"));
// [Ravi, Raj, Priya, Rita, Sam]
// Count by group
Map<Integer, Long> countByLength = [Link]()
.collect([Link](String::length, [Link]()));
// Partition into two groups (true/false)
Map<Boolean, List<Integer>> partitioned = [Link]()
.collect([Link](n -> n % 2 == 0));
// Convert to Map
Map<String, Integer> nameLengths = [Link]()
.collect([Link](n -> n, String::length));
7.5 Optional
Optional avoids NullPointerException by wrapping a value that may or may not be present.
// Creating Optional
Optional<String> opt1 = [Link]("Hello"); // non-null value
Optional<String> opt2 = [Link](); // empty Optional
Optional<String> opt3 = [Link](str); // null-safe
// Using Optional
[Link](); // true
[Link](); // false (Java 11+)
[Link](); // "Hello" (throws if empty!)
[Link]("default"); // value or default
[Link](() -> compute()); // lazy default
[Link](() -> new RuntimeException("Not found"));
[Link]([Link]::println); // run if present
[Link](String::length); // transform if present
[Link](s -> [Link]() > 3); // filter
// Chaining — avoids null checks!
String city = [Link](user)
.map(User::getAddress)
.map(Address::getCity)
.orElse("Unknown");
7.6 Default & Static Methods in Interfaces
interface Vehicle {
void start(); // abstract
default void stop() { // default — has body, can be overridden
[Link]("Vehicle stopped");
}
static Vehicle create() { // static — call via interface name
return new Car();
}
}
7.7 Other Java 8+ Features
Feature Description
var (Java 10) Type inference: var list = new ArrayList<String>()
Text Blocks (Java 15) Multi-line strings with triple quotes """..."""
Records (Java 16) Immutable data classes: record Point(int x, int y) {}
Sealed Classes (Java 17) Restrict which classes can extend: sealed class Shape permits Circle,
Rect
Pattern Matching instanceof (Java if (obj instanceof String s) { [Link](); }
16)
Switch Expressions (Java 14) yield keyword, lambda-style cases
LocalDate/LocalTime (Java 8) Modern date-time API in [Link] package
7.8 Date & Time API ([Link])
LocalDate date = [Link](); // 2024-01-15
LocalTime time = [Link](); // 14:30:45
LocalDateTime dateTime = [Link]();
ZonedDateTime zdt = [Link]([Link]("Asia/Kolkata"));
LocalDate birthday = [Link](2000, [Link], 15);
Period age = [Link](birthday, [Link]());
[Link]([Link]() + " years");
// Formatting
DateTimeFormatter fmt = [Link]("dd-MM-yyyy");
String formatted = [Link](fmt); // "15-01-2024"
LocalDate parsed = [Link]("15-01-2024", fmt);
// Duration between two times
Duration dur = [Link](time1, time2);
[Link](); [Link]();
CHAPTER 8: Data Structures & Algorithms (DSA)
DSA is tested in EVERY Java developer interview. Practice these core patterns.
8.1 Time & Space Complexity Quick Reference
Algorithm/Operation Time Space
Array access O(1) O(1)
Array search (linear) O(n) O(1)
Binary search O(log n) O(1)
ArrayList add O(1) amortized O(n)
HashMap get/put O(1) average O(n)
Bubble/Selection/ O(n²) O(1)
Insertion Sort
Merge Sort / Quick O(n log n) O(n)/O(log n)
Sort
BFS / DFS O(V+E) O(V)
8.2 Sorting Algorithms
Bubble Sort — O(n²)
void bubbleSort(int[] arr) {
int n = [Link];
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
Merge Sort — O(n log n)
void mergeSort(int[] arr, int l, int r) {
if (l < r) {
int mid = l + (r - l) / 2;
mergeSort(arr, l, mid);
mergeSort(arr, mid+1, r);
merge(arr, l, mid, r);
}
}
void merge(int[] arr, int l, int m, int r) {
int n1 = m-l+1, n2 = r-m;
int[] L = [Link](arr, l, m+1);
int[] R = [Link](arr, m+1, r+1);
int i=0, j=0, k=l;
while (i<n1 && j<n2) arr[k++] = L[i]<=R[j] ? L[i++] : R[j++];
while (i<n1) arr[k++] = L[i++];
while (j<n2) arr[k++] = R[j++];
}
8.3 Searching Algorithms
Binary Search — O(log n) — requires sorted array
int binarySearch(int[] arr, int target) {
int left = 0, right = [Link] - 1;
while (left <= right) {
int mid = left + (right - left) / 2; // avoids overflow
if (arr[mid] == target) return mid;
else if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1; // not found
}
8.4 Linked List
class ListNode {
int val;
ListNode next;
ListNode(int val) { [Link] = val; }
}
// Reverse Linked List
ListNode reverse(ListNode head) {
ListNode prev = null, curr = head;
while (curr != null) {
ListNode next = [Link];
[Link] = prev;
prev = curr;
curr = next;
}
return prev;
}
// Detect Cycle — Floyd's tortoise & hare
boolean hasCycle(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && [Link] != null) {
slow = [Link];
fast = [Link];
if (slow == fast) return true;
}
return false;
}
8.5 Stack & Queue Patterns
// Stack (use Deque as Stack)
Deque<Integer> stack = new ArrayDeque<>();
[Link](1); [Link](2); [Link](3);
[Link](); // 3 [Link](); // 2
// Valid Parentheses using Stack
boolean isValid(String s) {
Deque<Character> stack = new ArrayDeque<>();
for (char c : [Link]()) {
if (c == '(' || c == '[' || c == '{') [Link](c);
else {
if ([Link]()) return false;
char top = [Link]();
if (c == ')' && top != '(') return false;
if (c == ']' && top != '[') return false;
if (c == '}' && top != '{') return false;
}
}
return [Link]();
}
8.6 Binary Tree
class TreeNode {
int val; TreeNode left, right;
TreeNode(int val) { [Link] = val; }
}
// Inorder (Left-Root-Right) — gives sorted order for BST
void inorder(TreeNode root, List<Integer> result) {
if (root == null) return;
inorder([Link], result);
[Link]([Link]);
inorder([Link], result);
}
// BFS — Level Order Traversal
List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
if (root == null) return result;
Queue<TreeNode> q = new LinkedList<>();
[Link](root);
while (![Link]()) {
int size = [Link]();
List<Integer> level = new ArrayList<>();
for (int i = 0; i < size; i++) {
TreeNode node = [Link]();
[Link]([Link]);
if ([Link] != null) [Link]([Link]);
if ([Link] != null) [Link]([Link]);
}
[Link](level);
}
return result;
}
// Max depth
int maxDepth(TreeNode root) {
if (root == null) return 0;
return 1 + [Link](maxDepth([Link]), maxDepth([Link]));
}
8.7 HashMap-based Interview Patterns
Two Sum — O(n)
int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < [Link]; i++) {
int complement = target - nums[i];
if ([Link](complement)) {
return new int[]{[Link](complement), i};
}
[Link](nums[i], i);
}
return new int[]{};
}
Frequency Count Pattern
// Find most frequent element
int mostFrequent(int[] nums) {
Map<Integer, Integer> freq = new HashMap<>();
for (int n : nums) [Link](n, 1, Integer::sum);
return [Link]([Link](),
[Link]()).getKey();
}
8.8 Recursion & Dynamic Programming
Fibonacci with Memoization
Map<Integer, Long> memo = new HashMap<>();
long fib(int n) {
if (n <= 1) return n;
if ([Link](n)) return [Link](n);
long result = fib(n-1) + fib(n-2);
[Link](n, result);
return result;
}
Longest Common Subsequence — DP
int lcs(String s1, String s2) {
int m = [Link](), n = [Link]();
int[][] dp = new int[m+1][n+1];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if ([Link](i-1) == [Link](j-1))
dp[i][j] = dp[i-1][j-1] + 1;
else
dp[i][j] = [Link](dp[i-1][j], dp[i][j-1]);
}
}
return dp[m][n];
}
CHAPTER 9: JDBC — Java Database Connectivity
JDBC allows Java to connect to databases like MySQL, PostgreSQL, Oracle. Know the 5-step process.
9.1 JDBC Architecture & 5 Steps
4. Load Driver ([Link])
5. Create Connection ([Link])
6. Create Statement
7. Execute Query
8. Close Resources
9.2 Complete JDBC Example
import [Link].*;
public class JdbcDemo {
static final String URL = "jdbc:mysql://localhost:3306/mydb";
static final String USER = "root";
static final String PASS = "password";
public static void main(String[] args) {
// Step 1: Load driver (auto in JDBC 4.0+, optional)
// [Link]("[Link]");
// Steps 2-5 using try-with-resources
try (Connection conn = [Link](URL, USER, PASS);
Statement stmt = [Link]()) {
// Create table
[Link]("CREATE TABLE IF NOT EXISTS students " +
"(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50),
marks INT)");
// Insert
[Link]("INSERT INTO students(name,marks)
VALUES('Ravi',85)");
// Select
ResultSet rs = [Link]("SELECT * FROM students");
while ([Link]()) {
int id = [Link]("id");
String name = [Link]("name");
int marks = [Link]("marks");
[Link]("%d | %s | %d%n", id, name, marks);
}
} catch (SQLException e) {
[Link]();
}
}
}
9.3 PreparedStatement — Preferred (prevents SQL Injection)
String sql = "INSERT INTO students(name, marks) VALUES(?, ?)";
try (PreparedStatement pstmt = [Link](sql)) {
[Link](1, "Priya");
[Link](2, 92);
[Link]();
// Batch insert
for (String[] student : students) {
[Link](1, student[0]);
[Link](2, [Link](student[1]));
[Link]();
}
[Link]();
}
// SELECT with PreparedStatement
String query = "SELECT * FROM students WHERE marks > ?";
try (PreparedStatement ps = [Link](query)) {
[Link](1, 80);
ResultSet rs = [Link]();
while ([Link]()) { ... }
}
9.4 Transactions
try {
[Link](false); // begin transaction
// Operation 1 — debit
[Link]();
// Operation 2 — credit
[Link]();
[Link](); // all success — commit
} catch (Exception e) {
[Link](); // any failure — rollback
throw e;
} finally {
[Link](true);
}
9.5 Statement Types
Type Use Case
Statement Simple, static SQL (no parameters). Vulnerable to SQL injection.
PreparedStatement Parameterized SQL (?). Compiled once, executes many times. Safe.
Preferred.
CallableStatement Call stored procedures: {call sp_name(?, ?)}
CHAPTER 10: Spring Boot Essentials
Spring Boot makes it easy to build production-ready Spring applications. It's the #1 framework for Java
backend development.
10.1 Spring Core Concepts
Concept Description
IoC (Inversion of Control) Spring manages object creation — you don't use 'new'. Objects are
created & managed by Spring Container.
Dependency Injection (DI) Spring injects dependencies into your classes. Constructor injection
(preferred) or field injection (@Autowired).
Bean Any object managed by Spring Container. Annotated with
@Component, @Service, @Repository, @Controller, etc.
ApplicationContext Spring container — creates, manages, wires all beans.
Auto-configuration Spring Boot auto-configures beans based on classpath dependencies.
10.2 Spring Boot Annotations
Annotation Purpose
@SpringBootApplication Main class. Combines @Configuration + @EnableAutoConfiguration +
@ComponentScan
@Component Generic Spring bean
@Service Business logic layer bean
@Repository Data access layer bean. Exception translation.
@Controller MVC controller (returns views)
@RestController REST API controller = @Controller + @ResponseBody
@Autowired Inject dependency (prefer constructor injection)
@Configuration Class that defines beans using @Bean methods
@Bean Method that returns a Spring-managed object
@Value("${key}") Inject value from [Link]
@Qualifier("name") Specify which bean to inject when multiple exist
@Scope("prototype") Bean scope: singleton (default), prototype, request, session
10.3 Building a REST API
// 1. Main Class
@SpringBootApplication
public class AppApplication {
public static void main(String[] args) {
[Link]([Link], args);
}
}
// 2. Model
public class Product {
private Long id;
private String name;
private double price;
// constructors, getters, setters
}
// 3. Repository (Spring Data JPA)
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
List<Product> findByNameContaining(String keyword); // derived query
@Query("SELECT p FROM Product p WHERE [Link] < :price")
List<Product> findCheaperThan(@Param("price") double price);
}
// 4. Service Layer
@Service
public class ProductService {
private final ProductRepository repo;
// Constructor injection (preferred over @Autowired on field)
public ProductService(ProductRepository repo) { [Link] = repo; }
public List<Product> getAllProducts() { return [Link](); }
public Product getById(Long id) {
return [Link](id).orElseThrow(() -> new RuntimeException("Not
found"));
}
public Product create(Product p) { return [Link](p); }
public void delete(Long id) { [Link](id); }
}
// 5. REST Controller
@RestController
@RequestMapping("/api/products")
public class ProductController {
private final ProductService service;
public ProductController(ProductService service) { [Link] = service; }
@GetMapping
public List<Product> getAll() { return [Link](); }
@GetMapping("/{id}")
public ResponseEntity<Product> getById(@PathVariable Long id) {
return [Link]([Link](id));
}
@PostMapping
public ResponseEntity<Product> create(@RequestBody Product p) {
Product saved = [Link](p);
return [Link]([Link]).body(saved);
}
@PutMapping("/{id}")
public ResponseEntity<Product> update(@PathVariable Long id, @RequestBody
Product p) {
[Link](id);
return [Link]([Link](p));
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
[Link](id);
return [Link]().build();
}
}
10.4 HTTP Methods & REST Conventions
HTTP Method Action & Example
GET Read/fetch data. GET /api/products → list. GET /api/products/1 →
single item
POST Create new resource. POST /api/products with JSON body
PUT Update (replace) entire resource. PUT /api/products/1
PATCH Partial update. PATCH /api/products/1
DELETE Remove resource. DELETE /api/products/1
10.5 [Link]
# Server
[Link]=8080
# Database (MySQL)
[Link]=jdbc:mysql://localhost:3306/mydb
[Link]=root
[Link]=secret
[Link]-class-name=[Link]
# JPA / Hibernate
[Link]-auto=update # create / update / validate / none
[Link]-sql=true # print SQL queries
[Link].format_sql=true
# App custom properties
[Link]=mySecretKey
[Link]=10MB
# Logging
[Link]=INFO
[Link]=DEBUG
10.6 Spring Data JPA Annotations
Annotation Purpose
@Entity Class maps to a database table
@Table(name="tbl") Specify table name
@Id Primary key field
@GeneratedValue(strategy=Gen Auto-increment PK
[Link])
@Column(name="col", Column mapping with constraints
nullable=false)
@OneToMany / @ManyToOne Relationships between entities
@JoinColumn(name="fk") Foreign key column
@Transient Field not persisted to DB
@CreatedDate / Audit timestamps (with @EnableJpaAuditing)
@LastModifiedDate
10.7 Request Annotations in Controller
@GetMapping("/search")
public List<Product> search(
@RequestParam(defaultValue = "") String keyword, // ?keyword=java
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) { ... }
@GetMapping("/{id}/reviews/{reviewId}")
public Review get(
@PathVariable Long id,
@PathVariable Long reviewId) { ... }
@PostMapping
public Product create(
@RequestBody @Valid Product p, // parse JSON body; @Valid runs validation
@RequestHeader("Authorization") String token) { ... }
10.8 Global Exception Handling
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler([Link])
public ResponseEntity<String> handleRuntime(RuntimeException e) {
return [Link](HttpStatus.NOT_FOUND).body([Link]());
}
@ExceptionHandler([Link])
public ResponseEntity<Map<String, String>> handleValidation(
MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
[Link]().getFieldErrors().forEach(err ->
[Link]([Link](), [Link]()));
return [Link]().body(errors);
}
}
CHAPTER 11: Design Patterns
Design patterns are reusable solutions to common problems. Know at least: Singleton, Factory, Builder,
Observer, Strategy.
11.1 Singleton Pattern
Ensures only ONE instance of a class exists throughout the application.
public class DatabaseConnection {
private static volatile DatabaseConnection instance;
private Connection conn;
private DatabaseConnection() { // private constructor
// expensive initialization
}
// Thread-safe lazy initialization
public static DatabaseConnection getInstance() {
if (instance == null) {
synchronized ([Link]) {
if (instance == null) { // double-check locking
instance = new DatabaseConnection();
}
}
}
return instance;
}
}
11.2 Factory Pattern
Creates objects without exposing instantiation logic. Delegates object creation to a factory.
interface Shape { void draw(); }
class Circle implements Shape { public void draw() { [Link]("Circle");
} }
class Rectangle implements Shape { public void draw()
{ [Link]("Rectangle"); } }
class ShapeFactory {
public static Shape create(String type) {
return switch ([Link]()) {
case "circle" -> new Circle();
case "rectangle" -> new Rectangle();
default -> throw new IllegalArgumentException("Unknown: " + type);
};
}
}
// Usage — client doesn't know which class is instantiated
Shape shape = [Link]("circle");
[Link]();
11.3 Builder Pattern
Constructs complex objects step by step. Great for objects with many optional fields.
public class Person {
private final String name; // required
private final int age; // required
private final String email; // optional
private final String phone; // optional
private Person(Builder builder) {
[Link] = [Link];
[Link] = [Link];
[Link] = [Link];
[Link] = [Link];
}
public static class Builder {
private final String name;
private final int age;
private String email = "";
private String phone = "";
public Builder(String name, int age) {
[Link] = name; [Link] = age;
}
public Builder email(String email) { [Link] = email; return this; }
public Builder phone(String phone) { [Link] = phone; return this; }
public Person build() { return new Person(this); }
}
}
// Usage — clean, readable
Person p = new [Link]("Ravi", 25)
.email("ravi@[Link]")
.phone("+91-9876543210")
.build();
11.4 Observer Pattern
One-to-many dependency. When one object changes state, all its dependents are notified automatically.
interface Observer { void update(String event); }
class EventSource {
private List<Observer> observers = new ArrayList<>();
public void subscribe(Observer o) { [Link](o); }
public void unsubscribe(Observer o) { [Link](o); }
public void notifyAll(String event) {
[Link](o -> [Link](event));
}
public void doAction(String action) {
[Link]("Action: " + action);
notifyAll(action); // notify all subscribers
}
}
// Usage
EventSource source = new EventSource();
[Link](event -> [Link]("Logger: " + event));
[Link](event -> [Link]("Email: sent for " + event));
[Link]("USER_LOGIN"); // both observers get notified
11.5 Strategy Pattern
Define a family of algorithms, encapsulate each one, and make them interchangeable.
interface SortStrategy { void sort(int[] arr); }
class BubbleSort implements SortStrategy { public void sort(int[] arr) { /* ... */
} }
class QuickSort implements SortStrategy { public void sort(int[] arr) { /* ... */
} }
class Sorter {
private SortStrategy strategy;
public void setStrategy(SortStrategy s) { [Link] = s; }
public void sort(int[] arr) { [Link](arr); }
}
// Switch algorithms at runtime
Sorter sorter = new Sorter();
[Link](new QuickSort());
[Link](data);
[Link](new BubbleSort()); // easily swap algorithm
CHAPTER 12: Interview Q&A Cheat Sheet
These are the most frequently asked Java interview questions for freshers. Know these cold!
12.1 Core Java Q&A
Question Answer
What is the difference between == compares references (memory addresses). equals() compares
== and equals()? content/logical equality. Always use equals() for Strings and objects.
What is String Pool? Area in heap where String literals are stored. JVM reuses pool strings
to save memory. new String() bypasses the pool.
Why is String immutable? Security (can't change class names after loading), thread safety
(shared safely), performance (pooling). Once created, content cannot
change.
What is autoboxing/unboxing? Auto-conversion between primitive (int) and wrapper class (Integer).
Boxing: int→Integer. Unboxing: Integer→int. Done automatically by
compiler.
Difference between ArrayList and ArrayList: backed by array, O(1) random access, O(n) insert/delete.
LinkedList? LinkedList: doubly-linked nodes, O(1) insert/delete at ends, O(n)
access.
What is the difference between HashMap: O(1) ops, no order, allows null key. TreeMap: O(log n) ops,
HashMap and TreeMap? sorted by key, no null key.
What is the difference between Abstract class: can have state (fields), constructors, any access
abstract class and interface? modifier. Interface: all fields are constants, Java 8+ allows default/static
methods. Class extends one abstract class but implements multiple
interfaces.
What is method overloading vs Overloading: same name, different params, same class, compile-time.
overriding? Overriding: same name+params, subclass, runtime. @Override
annotation recommended.
What is the final keyword? final variable = constant (can't reassign). final method = can't override.
final class = can't subclass. e.g. String class is final.
What is a Singleton pattern? Design pattern ensuring only one instance of a class exists. Private
constructor, static instance, static getInstance() method with double-
checked locking.
12.2 OOP Q&A
Question Answer
What are the 4 pillars of OOP? Encapsulation (hiding data with getters/setters), Inheritance (reuse via
extends), Polymorphism (one interface, many implementations),
Abstraction (hiding complexity, showing only essentials).
Can we override static methods? No. Static methods are method-hiding, not overriding. They belong to
the class, not instance. @Override on static method gives compile
error.
What is 'this' keyword? Reference to the current object instance. Used to distinguish instance
variables from parameters, call another constructor (this()), or pass
current object as argument.
What is 'super' keyword? Reference to parent class. super() calls parent constructor (must be
first line). [Link]() calls parent's overridden method.
Can constructor be private? Yes. Used in Singleton pattern and utility classes. Prevents
instantiation from outside the class.
12.3 Collections Q&A
Question Answer
What is the default capacity of 10. When full, grows to 1.5x (newCapacity = oldCapacity +
ArrayList? oldCapacity/2). Initial capacity can be specified: new ArrayList<>(50).
How does HashMap work Uses array of Node (bucket). Key's hashCode() is computed, index =
internally? hash % capacity. If collision (same index), nodes are stored as
LinkedList (or Tree if >8 nodes in Java 8+). equals() checks key
equality.
What is Thrown when collection is modified while iterating (structurally). Use
ConcurrentModificationException [Link]() or CopyOnWriteArrayList or collect changes and
? apply after loop.
Difference between Iterator and Iterator: forward only, works on any Collection. ListIterator: bidirectional
ListIterator? (next/previous), can add/set, only for List.
What is fail-fast and fail-safe Fail-fast: throws ConcurrentModificationException if modified during
iterator? iteration (ArrayList, HashMap). Fail-safe: works on a copy, no
exception (ConcurrentHashMap, CopyOnWriteArrayList).
12.4 Java 8 Q&A
Question Answer
What is a functional interface? Interface with exactly ONE abstract method. Can be used as lambda
target. @FunctionalInterface annotation (optional but good practice).
Examples: Runnable, Comparator, Predicate, Function.
What is a lambda expression? Anonymous function: (params) -> body. Shorter way to implement
functional interfaces. Can access effectively-final local variables
(closure).
What is [Link]() vs filter() is a stream intermediate operation that returns a new stream
[Link]()? (doesn't modify original). removeIf() modifies the collection in place
(removes elements matching predicate).
What is Optional? Why use it? Container that may or may not contain a value. Avoids
NullPointerException. Forces caller to handle absent case explicitly
with orElse(), orElseThrow(), ifPresent().
What is the difference between map(): transforms each element 1-to-1. flatMap(): transforms each
map() and flatMap()? element to a stream, then flattens all into one stream. Use flatMap for
List<List<T>> to get List<T>.
12.5 Multithreading Q&A
Question Answer
What is deadlock? How to Two threads wait for each other indefinitely, blocking forever.
prevent it? Prevention: always acquire locks in the same order, use timeouts
(tryLock), use lock-free data structures (AtomicInteger).
What is the difference between wait(): releases lock, must be called in synchronized block, woken by
wait() and sleep()? notify()/notifyAll(). sleep(): doesn't release lock, pauses thread for time
duration, called anywhere.
What is a race condition? When two threads access shared data concurrently and the result
depends on execution order. Fix with synchronized, volatile, or atomic
variables.
What is thread-safety? Code is thread-safe if it works correctly when accessed by multiple
threads simultaneously. Achieve via: synchronization, immutable
objects, ThreadLocal, concurrent collections.
12.6 Spring Boot Q&A
Question Answer
What is Spring Boot vs Spring Spring Framework: core IoC/DI container + many modules. Spring
Framework? Boot: opinionated Spring that auto-configures everything, embeds
server (Tomcat), no XML config, production-ready with Actuator.
What is @SpringBootApplication? Convenience annotation combining @Configuration (bean definitions),
@EnableAutoConfiguration (auto-setup), @ComponentScan (scan for
beans). Put on main class.
What is Dependency Injection? Spring creates and provides dependencies to your class instead of you
creating them with 'new'. Types: Constructor injection (preferred,
immutable), Setter injection, Field injection (@Autowired).
What is JPA and Hibernate? JPA (Java Persistence API) is a specification for ORM. Hibernate is the
most popular JPA implementation. Spring Data JPA makes it even
easier with repository pattern.
What is @Transactional? Marks a method/class to run within a database transaction. On
exception, automatically rolls back. On success, commits. Prevents
partial updates.
12.7 Quick Reference — Time Complexities
Operation Time Complexity
[Link](i) O(1)
[Link](end) O(1) amortized
[Link](middle) O(n)
[Link](ends) O(1)
[Link]/put O(1) avg, O(n) worst
[Link]/put O(log n)
[Link] O(1) avg
[Link] O(log n)
[Link] O(1)
[Link] O(log n)
[Link] (primitives) O(n log n) - dual-pivot quicksort
[Link] (objects) O(n log n) - Timsort
Binary Search O(log n)
[Link]() O(1)
String concatenation (+) in loop O(n²) — use StringBuilder
12.8 Final Tips for Interviews
ALWAYS DO THESE:
1. Think out loud — interviewers want to hear your reasoning process 2. Clarify requirements before coding
— ask about edge cases 3. Start with brute force, then optimize 4. Write clean code — meaningful variable
names, proper indentation 5. Test your code with examples before saying done 6. Know the time and
space complexity of your solution 7. Practice on LeetCode: Easy 50 problems + Medium 50 problems
minimum
TOP COMPANIES' FOCUS AREAS:
Infosys/TCS/Wipro: Core Java, OOP, Collections, JDBC, basic Spring Product companies (Flipkart, Zomato
etc.): DSA + Java 8 + Spring Boot Startups: Spring Boot REST APIs + Database + System Design basics
Best of luck with your Java journey! 🚀
Core Java → OOP → Collections → Java 8 → DSA → Spring Boot → Get Hired!