LearnThatStack Ace your next interview

Java.
Interview cheat sheet.

Quick reference for Java - sectioned for fast scanning. Skim the part you're shaky on, walk in confident.

Backend Development 14-section reference ~17 min read

Summary

Java is a robust, object-oriented programming language widely used for enterprise backend development. This cheatsheet covers essential Java concepts including fundamentals, OOP principles, collections framework, multithreading, exception handling, Java 8+ features (lambdas, streams, optionals), Spring Framework ecosystem, JPA/Hibernate for database operations, REST API development, design patterns, and best practices. Key features include platform independence (JVM), strong type system, automatic memory management, rich standard library, and comprehensive frameworks like Spring Boot for rapid application development.

Java Fundamentals

Data Types

Primitive Types:

  • byte (8 bits), short (16), int (32), long (64)
  • float (32 bits), double (64)
  • char (16 bits Unicode)
  • boolean (true/false)

Reference Types: Objects, Arrays, Interfaces

String

String s1 = "Hello";  // String pool
String s2 = new String("Hello");  // Heap
s1 == s2;  // false (different objects)
s1.equals(s2);  // true (same content)

// String is immutable
StringBuilder sb = new StringBuilder();  // Mutable, not thread-safe
StringBuffer sbuf = new StringBuffer();  // Mutable, thread-safe

Arrays

int[] arr = new int[5];
int[] arr2 = {1, 2, 3, 4, 5};
int[][] matrix = new int[3][3];

Object-Oriented Programming

Four Pillars of OOP

1. Encapsulation

public class Person {
    private String name;  // Hidden data
    
    public String getName() { return name; }  // Controlled access
    public void setName(String name) { this.name = name; }
}

2. Inheritance

public class Employee extends Person {
    private double salary;
    // Inherits name, getName(), setName()
}

3. Polymorphism

// Method Overloading (Compile-time)
public int add(int a, int b) { return a + b; }
public double add(double a, double b) { return a + b; }

// Method Overriding (Runtime)
@Override
public String toString() { return "Custom string"; }

4. Abstraction

abstract class Animal {
    abstract void makeSound();  // No implementation
}

interface Flyable {
    void fly();  // All methods are abstract by default
}

Access Modifiers

  • private: Same class only
  • default (no modifier): Same package
  • protected: Same package + subclasses
  • public: Everywhere

Keywords

  • final: Cannot be changed (variable), overridden (method), extended (class)
  • static: Belongs to class, not instance
  • abstract: Must be implemented by subclass
  • synchronized: Thread-safe access
  • volatile: Variable always read from main memory

Collections Framework

List Interface

List<String> arrayList = new ArrayList<>();  // Dynamic array, O(1) access
List<String> linkedList = new LinkedList<>();  // Doubly-linked, O(1) insert/delete
List<String> vector = new Vector<>();  // Thread-safe ArrayList

Set Interface

Set<String> hashSet = new HashSet<>();  // No order, O(1) operations
Set<String> linkedHashSet = new LinkedHashSet<>();  // Insertion order
Set<String> treeSet = new TreeSet<>();  // Sorted, O(log n)

Map Interface

Map<String, Integer> hashMap = new HashMap<>();  // No order, O(1)
Map<String, Integer> linkedHashMap = new LinkedHashMap<>();  // Insertion order
Map<String, Integer> treeMap = new TreeMap<>();  // Sorted by key
Map<String, Integer> hashtable = new Hashtable<>();  // Thread-safe

Queue Interface

Queue<String> queue = new LinkedList<>();
queue.offer("item");  // Add
queue.poll();  // Remove and return
queue.peek();  // View without removing

Deque<String> deque = new ArrayDeque<>();  // Double-ended queue
PriorityQueue<Integer> pq = new PriorityQueue<>();  // Min heap by default

Important Methods

// Common operations
list.add(element);
list.remove(index);
list.get(index);
list.size();

set.add(element);
set.contains(element);
set.remove(element);

map.put(key, value);
map.get(key);
map.containsKey(key);
map.keySet();
map.values();
map.entrySet();

Multithreading & Concurrency

Creating Threads

// Method 1: Extending Thread
class MyThread extends Thread {
    public void run() { /* task */ }
}

// Method 2: Implementing Runnable
class MyRunnable implements Runnable {
    public void run() { /* task */ }
}
Thread t = new Thread(new MyRunnable());

// Method 3: Lambda (Java 8+)
Thread t = new Thread(() -> { /* task */ });

Thread States

  1. NEW: Created but not started
  2. RUNNABLE: Executing or ready to execute
  3. BLOCKED: Waiting for monitor lock
  4. WAITING: Waiting indefinitely
  5. TIMED_WAITING: Waiting for specified time
  6. TERMINATED: Completed execution

Synchronization

// Synchronized method
public synchronized void method() { /* thread-safe */ }

// Synchronized block
synchronized(this) { /* critical section */ }

// ReentrantLock
ReentrantLock lock = new ReentrantLock();
lock.lock();
try { /* critical section */ }
finally { lock.unlock(); }

Concurrent Collections

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
BlockingQueue<String> queue = new LinkedBlockingQueue<>();

ExecutorService

ExecutorService executor = Executors.newFixedThreadPool(5);
executor.submit(() -> { /* task */ });
executor.shutdown();

// Other executors
Executors.newSingleThreadExecutor();
Executors.newCachedThreadPool();
Executors.newScheduledThreadPool(5);

Exception Handling

Hierarchy

Throwable
├── Error (Don't catch)
└── Exception
    ├── RuntimeException (Unchecked)
    │   ├── NullPointerException
    │   ├── ArrayIndexOutOfBoundsException
    │   └── IllegalArgumentException
    └── IOException (Checked)
        └── FileNotFoundException

Try-Catch-Finally

try {
    // Risky code
} catch (IOException e) {
    // Handle specific exception
} catch (Exception e) {
    // Handle general exception
} finally {
    // Always executes (cleanup)
}

Try-with-Resources

try (FileReader fr = new FileReader("file.txt")) {
    // Use resource
} catch (IOException e) {
    // Handle exception
}  // Auto-closes resource

Custom Exceptions

public class CustomException extends Exception {
    public CustomException(String message) {
        super(message);
    }
}

Java 8+ Features

Lambda Expressions

// Before Java 8
Comparator<String> comp = new Comparator<String>() {
    public int compare(String s1, String s2) {
        return s1.compareTo(s2);
    }
};

// Java 8+
Comparator<String> comp = (s1, s2) -> s1.compareTo(s2);

Stream API

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// Filter, map, reduce
int sum = numbers.stream()
    .filter(n -> n % 2 == 0)
    .map(n -> n * 2)
    .reduce(0, Integer::sum);

// Collectors
List<String> filtered = list.stream()
    .filter(s -> s.startsWith("A"))
    .collect(Collectors.toList());

Map<Integer, List<String>> grouped = list.stream()
    .collect(Collectors.groupingBy(String::length));

Optional

Optional<String> optional = Optional.ofNullable(getString());
optional.ifPresent(System.out::println);
String value = optional.orElse("default");
String value2 = optional.orElseThrow(() -> new Exception());

Functional Interfaces

// Predicate<T> - test()
Predicate<Integer> isEven = n -> n % 2 == 0;

// Function<T,R> - apply()
Function<String, Integer> strLength = String::length;

// Consumer<T> - accept()
Consumer<String> printer = System.out::println;

// Supplier<T> - get()
Supplier<Double> random = Math::random;

Default & Static Methods in Interfaces

interface MyInterface {
    default void defaultMethod() { /* implementation */ }
    static void staticMethod() { /* implementation */ }
}

Spring Framework

Core Concepts

  • IoC (Inversion of Control): Container manages object lifecycle
  • DI (Dependency Injection): Dependencies provided by container

Annotations

@Component  // Generic component
@Service    // Service layer
@Repository // Data access layer
@Controller // Web controller
@RestController  // @Controller + @ResponseBody

@Autowired  // Dependency injection
@Qualifier("beanName")  // Specify which bean
@Primary    // Default bean when multiple exist

@Configuration  // Java config class
@Bean       // Method produces a bean
@Value("${property}")  // Inject property value

Spring Boot

@SpringBootApplication  // @Configuration + @EnableAutoConfiguration + @ComponentScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

REST Controller

@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) { }
    
    @PostMapping
    public User createUser(@RequestBody User user) { }
    
    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) { }
    
    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) { }
}

Request Mappings

  • @GetMapping - GET requests
  • @PostMapping - POST requests
  • @PutMapping - PUT requests
  • @DeleteMapping - DELETE requests
  • @PatchMapping - PATCH requests

Parameter Annotations

  • @PathVariable - URL path variables
  • @RequestParam - Query parameters
  • @RequestBody - Request body
  • @RequestHeader - HTTP headers

Database & JPA

JPA Annotations

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true)
    private String email;
    
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private List<Order> orders;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id")
    private Department department;
}

Repository

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    // Custom queries
    Optional<User> findByEmail(String email);
    List<User> findByAgeGreaterThan(int age);
    
    @Query("SELECT u FROM User u WHERE u.name = ?1")
    User findByNameCustom(String name);
    
    @Modifying
    @Query("UPDATE User u SET u.active = false WHERE u.id = :id")
    void deactivateUser(@Param("id") Long id);
}

Transaction Management

@Service
@Transactional
public class UserService {
    @Transactional(readOnly = true)
    public User getUser(Long id) { }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void createUser(User user) { }
}

Fetch Types

  • EAGER: Load immediately
  • LAZY: Load when accessed

Cascade Types

  • PERSIST: Save child when parent saved
  • MERGE: Update child when parent updated
  • REMOVE: Delete child when parent deleted
  • REFRESH: Refresh child when parent refreshed
  • ALL: All of the above

REST APIs

HTTP Methods

  • GET: Retrieve data
  • POST: Create new resource
  • PUT: Update entire resource
  • PATCH: Partial update
  • DELETE: Remove resource

Status Codes

  • 2xx Success: 200 OK, 201 Created, 204 No Content
  • 3xx Redirection: 301 Moved Permanently, 302 Found
  • 4xx Client Error: 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found
  • 5xx Server Error: 500 Internal Server Error, 503 Service Unavailable

REST Best Practices

// Resource naming (nouns, plural)
GET    /api/users          // Get all users
GET    /api/users/{id}     // Get specific user
POST   /api/users          // Create user
PUT    /api/users/{id}     // Update user
DELETE /api/users/{id}     // Delete user

// Filtering, sorting, pagination
GET /api/users?age=25&sort=name&page=2&size=10

Global Exception Handling

@ControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException e) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND)
            .body(new ErrorResponse(e.getMessage()));
    }
}

Design Patterns

Singleton

public class Singleton {
    private static volatile Singleton instance;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

Factory

public interface Shape { void draw(); }

public class ShapeFactory {
    public Shape getShape(String type) {
        switch(type) {
            case "CIRCLE": return new Circle();
            case "SQUARE": return new Square();
            default: return null;
        }
    }
}

Builder

public class User {
    private String name;
    private int age;
    
    private User(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
    }
    
    public static class Builder {
        private String name;
        private int age;
        
        public Builder name(String name) {
            this.name = name;
            return this;
        }
        
        public Builder age(int age) {
            this.age = age;
            return this;
        }
        
        public User build() {
            return new User(this);
        }
    }
}

// Usage: User user = new User.Builder().name("John").age(25).build();

Observer

public interface Observer {
    void update(String message);
}

public class Subject {
    private List<Observer> observers = new ArrayList<>();
    
    public void attach(Observer observer) {
        observers.add(observer);
    }
    
    public void notifyObservers(String message) {
        observers.forEach(o -> o.update(message));
    }
}

Best Practices

SOLID Principles

  1. Single Responsibility: Class should have one reason to change
  2. Open/Closed: Open for extension, closed for modification
  3. Liskov Substitution: Subtypes must be substitutable for base types
  4. Interface Segregation: Many specific interfaces better than one general
  5. Dependency Inversion: Depend on abstractions, not concretions

Code Quality

  • Use meaningful variable/method names
  • Keep methods small (< 20 lines)
  • Avoid deep nesting (max 3 levels)
  • Handle null checks appropriately
  • Use enums instead of constants
  • Prefer composition over inheritance
  • Write unit tests (aim for 80%+ coverage)

Performance Tips

  • Use StringBuilder for string concatenation in loops
  • Prefer ArrayList over LinkedList for random access
  • Use primitive types when possible
  • Cache expensive computations
  • Use lazy initialization where appropriate
  • Close resources properly (try-with-resources)
  • Avoid creating unnecessary objects

Security

  • Never store passwords as plain text
  • Validate all inputs
  • Use parameterized queries (prevent SQL injection)
  • Implement proper authentication/authorization
  • Keep dependencies updated
  • Follow OWASP guidelines

Key Concepts & Comparisons

Core Language Comparisons

Concept Comparison Key Differences Use Cases
== vs equals() Reference vs Content == compares memory addresses, equals() compares values Use equals() for content comparison
String vs StringBuilder Immutable vs Mutable String creates new objects, StringBuilder modifies existing Use StringBuilder in loops
ArrayList vs LinkedList Array vs Linked ArrayList O(1) access, LinkedList O(1) insert/delete ArrayList for reads, LinkedList for modifications
HashMap vs TreeMap Hash vs Tree HashMap O(1) avg, TreeMap O(log n) but sorted HashMap for performance, TreeMap for ordering
HashSet vs TreeSet Hash vs Tree HashSet O(1) avg, TreeSet O(log n) but sorted HashSet for performance, TreeSet for ordering
Checked vs Unchecked Compile vs Runtime Checked must be handled, Unchecked are optional Use checked for recoverable errors

Collection Performance Comparison

Collection Access Search Insert Delete Ordered Thread-Safe
ArrayList O(1) O(n) O(n) O(n) Yes No
LinkedList O(n) O(n) O(1) O(1) Yes No
Vector O(1) O(n) O(n) O(n) Yes Yes
HashMap N/A O(1) avg O(1) avg O(1) avg No No
TreeMap N/A O(log n) O(log n) O(log n) Yes No
HashSet N/A O(1) avg O(1) avg O(1) avg No No
TreeSet N/A O(log n) O(log n) O(log n) Yes No
ConcurrentHashMap N/A O(1) avg O(1) avg O(1) avg No Yes

Thread Safety Comparison

Class Thread Safe Alternative Use Case
ArrayList No Vector, Collections.synchronizedList() Single-threaded access
HashMap No ConcurrentHashMap, Hashtable Concurrent read/write operations
StringBuilder No StringBuffer String building in multi-threaded env
SimpleDateFormat No DateTimeFormatter (Java 8+) Date formatting

Memory Management & GC

Generation Purpose Collections Algorithms
Young Generation New objects Minor GC Copy, G1 Young
Eden Space Object creation Minor GC Objects die young
Survivor Spaces Objects surviving first GC Minor GC S0, S1 promotion
Old Generation Long-lived objects Major GC Mark-Sweep-Compact
Metaspace Class metadata Full GC Replaces PermGen

Exception Handling Strategy

Exception Type Examples Handling Strategy Best Practice
Checked IOException, SQLException Must catch or declare Use for recoverable errors
Unchecked NullPointerException, IllegalArgumentException Optional handling Use for programming errors
Error OutOfMemoryError, StackOverflowError Don't catch JVM issues, let application fail
Custom Business logic exceptions Extend Exception/RuntimeException Create meaningful exception hierarchies

Spring Framework Concepts

Component Purpose Annotation Scope
Component Generic spring component @Component Singleton (default)
Service Business logic layer @Service Singleton
Repository Data access layer @Repository Singleton
Controller Web layer @Controller Singleton
Configuration Java configuration @Configuration Singleton

Bean Scopes Comparison

Scope Description Use Case Lifecycle
Singleton One instance per container Stateless services Application lifetime
Prototype New instance each time Stateful objects Until garbage collected
Request One per HTTP request Web request data HTTP request lifetime
Session One per HTTP session User session data HTTP session lifetime
Application One per ServletContext Application-wide data Web application lifetime

JPA/Hibernate Concepts

Fetch Type Loading Strategy Performance Use Case
EAGER Immediate loading Higher memory usage Small, frequently accessed data
LAZY On-demand loading Lower memory usage Large collections, optional data
Cascade Type Operations Risk Level Use Case
PERSIST Save operations Low Parent-child creation
MERGE Update operations Low Detached entity updates
REMOVE Delete operations High Dependent entity cleanup
ALL All operations Very High Complete lifecycle management

REST API Best Practices

HTTP Method Purpose Idempotent Safe Response Code
GET Retrieve resource Yes Yes 200 OK
POST Create resource No No 201 Created
PUT Update/Replace resource Yes No 200 OK, 204 No Content
PATCH Partial update No No 200 OK, 204 No Content
DELETE Remove resource Yes No 200 OK, 204 No Content

Common Design Patterns

Pattern Type Use Case Implementation
Singleton Creational One instance needed Double-checked locking
Factory Creational Object creation logic Switch-based creation
Builder Creational Complex object construction Fluent interface
Observer Behavioral Event notification Subject-Observer relationship
Strategy Behavioral Algorithm selection Interface-based implementations
Decorator Structural Add behavior dynamically Wrapper pattern

Lambda & Stream Operations

Operation Type Example Use Case
filter() Intermediate stream.filter(x -> x > 5) Conditional filtering
map() Intermediate stream.map(String::toUpperCase) Transform elements
reduce() Terminal stream.reduce(0, Integer::sum) Aggregate to single value
collect() Terminal stream.collect(Collectors.toList()) Collect to collection
forEach() Terminal stream.forEach(System.out::println) Execute action on each
anyMatch() Terminal stream.anyMatch(x -> x > 10) Test if any match

Performance Optimization Tips

Issue Solution Implementation Impact
String Concatenation Use StringBuilder StringBuilder sb = new StringBuilder() Avoid O(n²) complexity
Autoboxing Use primitives int instead of Integer Reduce object creation
Large Collections Use appropriate size new ArrayList<>(expectedSize) Avoid resizing overhead
Database N+1 Use JOIN FETCH @Query("SELECT p FROM Post p JOIN FETCH p.comments") Reduce query count
Lazy Loading Initialize in transaction Use @Transactional or Open Session in View Avoid LazyInitializationException

Security Best Practices

Vulnerability Prevention Implementation Example
SQL Injection Parameterized queries Use @Query with parameters @Query("SELECT u FROM User u WHERE u.id = :id")
XSS Input validation/escaping Use validation annotations @NotBlank, @Email
CSRF CSRF tokens Spring Security default Enable CSRF protection
Sensitive Data Encryption/Hashing BCrypt for passwords BCryptPasswordEncoder
Authorization Role-based access Spring Security @PreAuthorize("hasRole('ADMIN')")

Common Coding Solutions

// String reversal
public String reverse(String str) {
    return new StringBuilder(str).reverse().toString();
}

// Palindrome check
public boolean isPalindrome(String str) {
    String cleaned = str.replaceAll("[^a-zA-Z0-9]", "").toLowerCase();
    return cleaned.equals(new StringBuilder(cleaned).reverse().toString());
}

// Find duplicates in array
public Set<Integer> findDuplicates(int[] nums) {
    Set<Integer> seen = new HashSet<>();
    Set<Integer> duplicates = new HashSet<>();
    for (int num : nums) {
        if (!seen.add(num)) {
            duplicates.add(num);
        }
    }
    return duplicates;
}

// Two sum problem
public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement)) {
            return new int[]{map.get(complement), i};
        }
        map.put(nums[i], i);
    }
    return new int[0];
}

// Binary search
public int binarySearch(int[] arr, int target) {
    int left = 0, right = arr.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (arr[mid] == target) return mid;
        if (arr[mid] < target) left = mid + 1;
        else right = mid - 1;
    }
    return -1;
}

Database & ACID Properties

Property Description Example Failure Impact
Atomicity All or nothing Bank transfer: debit AND credit Partial transaction completion
Consistency Valid state to valid state Foreign key constraints Data integrity violations
Isolation Concurrent transactions don't interfere Transaction isolation levels Dirty reads, phantom reads
Durability Committed changes persist Write to disk Data loss on system failure

SQL vs NoSQL Decision Matrix

Factor SQL (RDBMS) NoSQL Decision Criteria
Schema Fixed, normalized Flexible, denormalized Stable vs evolving requirements
Scalability Vertical (limited) Horizontal (unlimited) Scale requirements
Transactions ACID compliant Eventually consistent Consistency requirements
Complexity Complex queries (JOINs) Simple operations Query complexity
Use Cases Financial, CRM Social media, IoT Data nature and access patterns

Quick Reference & Best Practices

Essential Java 8+ Features

Feature Syntax Example Use Case
Lambda (params) -> expression list.forEach(x -> System.out.println(x)) Functional programming
Method Reference Class::method list.stream().map(String::toUpperCase) Cleaner lambda syntax
Optional Optional<T> Optional.ofNullable(value).orElse(default) Null safety
Stream stream() list.stream().filter().map().collect() Data processing pipelines
Default Methods default returnType method() Interface evolution Backward compatibility

Performance & Memory Optimization

Optimization Problem Solution Impact
String Concatenation Creating many String objects Use StringBuilder or String.join() Avoid O(n²) complexity
Autoboxing Unnecessary object creation Use primitive types when possible Reduce GC pressure
Collection Sizing Dynamic resizing overhead Initialize with expected capacity Reduce array copying
Object Pooling Expensive object creation Reuse expensive objects Reduce allocation overhead
Lazy Initialization Unnecessary object creation Create objects when needed Save memory and startup time

Thread Safety Quick Reference

Class/Interface Thread Safe Alternative Use Case
ArrayList ❌ Vector, Collections.synchronizedList() List operations
HashMap ❌ ConcurrentHashMap, Hashtable Map operations
StringBuilder ❌ StringBuffer String building
SimpleDateFormat ❌ DateTimeFormatter Date formatting
Random ⚠️ ThreadLocalRandom Random number generation

Common Annotations Reference

Annotation Package Purpose Example
@Override java.lang Method overriding @Override public String toString()
@Deprecated java.lang Mark as deprecated @Deprecated public void oldMethod()
@SuppressWarnings java.lang Suppress compiler warnings @SuppressWarnings("unchecked")
@FunctionalInterface java.lang Mark functional interface @FunctionalInterface interface MyInterface
@Autowired Spring Dependency injection @Autowired private UserService userService
@Component Spring Spring component @Component public class MyComponent

Exception Handling Best Practices

// ✅ Good: Specific exception handling
try {
    // risky operation
} catch (SQLException e) {
    // handle database errors
    log.error("Database error: {}", e.getMessage());
    throw new ServiceException("Unable to process request", e);
} catch (IOException e) {
    // handle I/O errors
    log.error("I/O error: {}", e.getMessage());
    throw new ServiceException("File processing failed", e);
}

// ❌ Avoid: Catching generic Exception
try {
    // risky operation
} catch (Exception e) {
    // Too broad, might hide bugs
}

SOLID Principles in Practice

Principle Violation Solution
Single Responsibility Class handles user data AND email sending Separate User and EmailService classes
Open/Closed Modifying existing code for new features Use interfaces and polymorphism
Liskov Substitution Subclass changes expected behavior Ensure subclass can replace superclass
Interface Segregation Large interface with unused methods Create smaller, focused interfaces
Dependency Inversion Depending on concrete classes Depend on abstractions/interfaces

Time Complexity Reference

Data Structure Access Search Insertion Deletion
Array O(1) O(n) O(n) O(n)
ArrayList O(1) O(n) O(n) amortized O(n)
LinkedList O(n) O(n) O(1) O(1)
HashMap N/A O(1) avg, O(n) worst O(1) avg, O(n) worst O(1) avg, O(n) worst
TreeMap N/A O(log n) O(log n) O(log n)
HashSet N/A O(1) avg, O(n) worst O(1) avg, O(n) worst O(1) avg, O(n) worst
TreeSet N/A O(log n) O(log n) O(log n)

JVM Memory Areas

Area Purpose Contents GC Target
Heap Object storage Objects, arrays Major/Minor GC
Stack Method execution Local variables, method calls Automatic (scope-based)
Method Area Class information Class metadata, constants Full GC
PC Registers Execution tracking Current instruction pointer Not applicable
Native Method Stack Native calls Native method execution Not applicable

Spring Boot Configuration

# Database Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=user
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=false

# Server Configuration
server.port=8080
server.servlet.context-path=/api

# Logging Configuration
logging.level.com.example=DEBUG
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n

Common Interview Code Solutions

// Fibonacci sequence
public int fibonacci(int n) {
    if (n <= 1) return n;
    int a = 0, b = 1;
    for (int i = 2; i <= n; i++) {
        int temp = a + b;
        a = b;
        b = temp;
    }
    return b;
}

// Merge two sorted arrays
public int[] merge(int[] arr1, int[] arr2) {
    int[] result = new int[arr1.length + arr2.length];
    int i = 0, j = 0, k = 0;
    
    while (i < arr1.length && j < arr2.length) {
        result[k++] = arr1[i] <= arr2[j] ? arr1[i++] : arr2[j++];
    }
    while (i < arr1.length) result[k++] = arr1[i++];
    while (j < arr2.length) result[k++] = arr2[j++];
    
    return result;
}

// Check if string contains unique characters
public boolean hasUniqueChars(String str) {
    if (str.length() > 128) return false; // ASCII assumption
    boolean[] chars = new boolean[128];
    for (char c : str.toCharArray()) {
        if (chars[c]) return false;
        chars[c] = true;
    }
    return true;
}

Production Best Practices

✅ Development Best Practices

  • Use dependency injection for loose coupling
  • Write unit tests with high coverage (>80%)
  • Implement proper logging with appropriate levels
  • Use configuration files for environment-specific settings
  • Handle exceptions gracefully with meaningful messages
  • Follow naming conventions and code style guidelines

✅ Performance Best Practices

  • Use connection pooling for database connections
  • Implement caching for frequently accessed data
  • Use lazy loading for expensive operations
  • Profile application to identify bottlenecks
  • Optimize database queries and indexes
  • Use appropriate data structures for the use case

✅ Security Best Practices

  • Never store passwords in plain text
  • Use parameterized queries to prevent SQL injection
  • Validate and sanitize all user inputs
  • Implement proper authentication and authorization
  • Use HTTPS for all communications
  • Keep dependencies updated to latest secure versions

Testing Strategy

Test Type Scope Tools Purpose
Unit Tests Individual methods/classes JUnit, Mockito Test business logic
Integration Tests Component interaction TestContainers, @SpringBootTest Test component integration
Contract Tests API contracts Pact, Spring Cloud Contract Verify API compatibility
End-to-End Tests Full application flow Selenium, REST Assured Test user scenarios

Common JVM Tuning Parameters

# Memory settings
-Xms2g                    # Initial heap size
-Xmx4g                    # Maximum heap size
-XX:MetaspaceSize=256m    # Initial metaspace size

# Garbage Collection
-XX:+UseG1GC             # Use G1 garbage collector
-XX:MaxGCPauseMillis=100 # Target max GC pause time

# Monitoring
-XX:+PrintGCDetails      # Print GC information
-XX:+HeapDumpOnOutOfMemoryError  # Dump heap on OOM

Debugging & Monitoring Tools

Tool Purpose Usage Best For
JConsole JVM monitoring Built-in JDK tool Basic monitoring
VisualVM Profiling Free profiler Memory/CPU analysis
JProfiler Advanced profiling Commercial tool Deep performance analysis
Micrometer Metrics collection Spring Boot integration Production monitoring
SLF4J + Logback Logging Standard logging facade Application logging

Memory Management Tips

// ✅ Proper resource management
try (FileInputStream fis = new FileInputStream("file.txt")) {
    // Use resource
} catch (IOException e) {
    // Handle exception
} // Resource automatically closed

// ✅ Avoid memory leaks
// Clear collections when done
largeList.clear();
largeList = null;

// ✅ Use appropriate collection sizes
List<String> list = new ArrayList<>(expectedSize);
Map<String, String> map = new HashMap<>(expectedSize);
Found this useful? Pass it on.
Pro · $10/mo

The sheet is free. Pro goes deeper.

Pro opens the full question library behind every sheet, every refresher and a monthly AI allowance. One subscription, all formats.

Full question library All refreshers Cancel anytime