Skip to content

Java Interview Questions for 5 Years Experience

40 questions with answers for candidates with 5 years of experience — 2 easy, 23 medium, 15 hard.

What interviewers expect: 5 years experience

At five years, interviews include system design: scalable APIs, database choices, caching, messaging, consistency and failure handling. Interviewers expect JVM and GC tuning knowledge, deep concurrency, and stories of leading features, mentoring juniors and handling incidents. Coding rounds still appear, but design depth and trade-off discussions carry more weight. Expect questions on code review and estimation too.

This set is weighted towards JDBC, Hibernate and JPA (10), Multithreading and Concurrency (8), Java 8+ Features and Streams (6), Collections Framework (6).

System design JVM and GC tuning Distributed system patterns Technical leadership
Solved at this levelStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

Write a JDBC batch insert for a list of products.

Save to ▾
Show answer
Batching sends many rows in one round trip. String sql = "INSERT INTO product(name, price) VALUES (?, ?)"; try (Connection c = ds.getConnection(); PreparedStatement ps = c.prepareStatement(sql)) { c.setAutoCommit(false); int n = 0; for (Product p : products) { ps.setString(1, p.name()); ps.setLong(2, p.price()); ps.addBatch(); if (++n % 500 == 0) ps.executeBatch(); } ps.executeBatch(); c.commit(); }
02

What is Spring Boot and how is it different from the Spring Framework?

Save to ▾
Show answer
Spring Framework provides dependency injection, MVC, transactions and data access but needs manual configuration. Spring Boot builds on it with auto-configuration, starter dependencies, an embedded server such as Tomcat and production features through Actuator, so you can run a service with java -jar. Spring Boot 3 requires Java 17 or later and uses Jakarta EE packages instead of javax.
03

What is the difference between composition and inheritance, and which should you prefer?

Save to ▾
Show answer
Inheritance is an is-a relation where the subclass reuses parent code, but it creates tight coupling and fragile hierarchies. Composition is a has-a relation where a class holds another object and delegates work, such as a Car having an Engine. Prefer composition because it is flexible, allows changing behaviour at runtime and is easier to test. Use inheritance only for a true is-a relationship.
04

Write a custom unchecked exception and a Spring handler that returns HTTP 404.

Save to ▾
Show answer
Define the exception, then map it centrally. public class NotFoundException extends RuntimeException { public NotFoundException(String msg) { super(msg); } } @RestControllerAdvice public class ApiErrors { @ExceptionHandler(NotFoundException.class) public ProblemDetail notFound(NotFoundException e) { return ProblemDetail.forStatusAndDetail( HttpStatus.NOT_FOUND, e.getMessage()); } }
05

What are records in Java and when should you use them?

Save to ▾
Show answer
Records, final in Java 16, are concise classes for immutable data. record Point(int x, int y) {} generates private final fields, a canonical constructor, accessors, equals(), hashCode() and toString(). You can add validation in a compact constructor and add methods. Use them for DTOs, API responses and map keys. They cannot extend another class and are not suited to JPA entities, which need mutability.
06

Map a one-to-many relation between Order and OrderItem in JPA.

Save to ▾
Show answer
Make the child own the foreign key and keep both sides in sync. @Entity class Order { @Id @GeneratedValue Long id; @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true) List<OrderItem> items = new ArrayList<>(); void addItem(OrderItem i) { items.add(i); i.setOrder(this); } } @Entity class OrderItem { @Id @GeneratedValue Long id; @ManyToOne(fetch = FetchType.LAZY) Order order; }
07

How does Spring Boot auto-configuration work?

Save to ▾
Show answer
At startup Spring Boot reads auto-configuration classes listed in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. Each class uses conditions like @ConditionalOnClass, @ConditionalOnMissingBean and @ConditionalOnProperty, so it creates beans only when the library is on the classpath and you have not defined your own. Run with --debug to see the condition report showing what was applied and why.
08

Write a minimal Dockerfile for a Spring Boot application.

Save to ▾
Show answer
A multi-stage build keeps the image small. FROM eclipse-temurin:21-jdk AS build WORKDIR /app COPY . . RUN ./mvnw -q package -DskipTests FROM eclipse-temurin:21-jre WORKDIR /app COPY --from=build /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-XX:MaxRAMPercentage=75", "-jar", "app.jar"] Spring Boot can also build images without a Dockerfile using mvn spring-boot:build-image.
09

Explain the happens-before relationship in the Java Memory Model.

Save to ▾
Show answer
Happens-before is the rule that guarantees one action's effects are visible to another. Examples: unlocking a monitor happens-before a later lock of the same monitor, a volatile write happens-before later reads of it, Thread.start() happens-before actions in the started thread, and actions in a thread happen-before another thread's successful join() on it. Without such an edge, threads may see stale or reordered values.
10

What is the N+1 select problem in Hibernate and how do you fix it?

Save to ▾
Show answer
N+1 happens when you load N parent entities with one query and then a lazy association triggers one extra query per parent, giving N+1 queries. Fix it with a JOIN FETCH in JPQL, an @EntityGraph on the repository method, or batch fetching with @BatchSize or hibernate.default_batch_fetch_size. Detect it by enabling SQL logging or using a query count assertion in tests.
11

Flatten a list of lists of integers and compute the sum of squares of the even numbers.

Save to ▾
Show answer
flatMap then use a primitive stream to avoid boxing. int result = lists.stream() .flatMap(List::stream) .filter(n -> n % 2 == 0) .mapToInt(n -> n * n) .sum(); mapToInt returns an IntStream, whose sum() is simpler and faster than reduce on boxed Integers.
12

Two scheduled jobs on different servers process the same records twice. How do you prevent this?

Save to ▾
Show answer
In-JVM locks do not work across servers. Use a distributed lock such as ShedLock with a database table or Redis, so only one instance runs the job at a time. Make the processing idempotent too, for example by marking records with a status and updating with WHERE status = 'NEW' so only one worker claims each row. Database SELECT FOR UPDATE SKIP LOCKED also works well.
13

What does the volatile keyword guarantee?

Save to ▾
Show answer
volatile guarantees visibility and ordering: a write to a volatile field is immediately visible to other threads, and it prevents reordering around that access under the Java Memory Model. It does not make compound operations like count++ atomic, because that is a read, modify and write. Use it for flags such as a stop signal, and use AtomicInteger or locks for counters.
14

What are fail-fast and fail-safe iterators?

Save to ▾
Show answer
Fail-fast iterators, used by ArrayList and HashMap, throw ConcurrentModificationException if the collection is structurally modified during iteration other than through the iterator itself; they check a modCount. Fail-safe or weakly consistent iterators, as in ConcurrentHashMap and CopyOnWriteArrayList, work on a snapshot or tolerate changes and never throw, but may not show the latest updates.
15

Find the top K most frequent words in a list.

Save to ▾
Show answer
Count with a map, then keep a min-heap of size K. Map<String, Integer> cnt = new HashMap<>(); for (String w : words) cnt.merge(w, 1, Integer::sum); PriorityQueue<String> pq = new PriorityQueue<>( Comparator.comparingInt(cnt::get)); for (String w : cnt.keySet()) { pq.offer(w); if (pq.size() > k) pq.poll(); } Time O(n log k). Reverse the heap contents for highest first.
16

Using streams, find the employee with the highest salary in each department.

Save to ▾
Show answer
Group by department with a maxBy downstream collector. Map<String, Optional<Employee>> top = employees.stream() .collect(Collectors.groupingBy( Employee::department, Collectors.maxBy(Comparator.comparingInt(Employee::salary)))); To get values without Optional, wrap with collectingAndThen(maxBy(...), Optional::get), which is safe because each group has at least one element.
17

When should you avoid parallel streams?

Save to ▾
Show answer
Parallel streams use the common ForkJoinPool and help only for large, CPU-bound, stateless work on sources that split well, like arrays and ArrayList. Avoid them for small data, I/O or blocking calls, LinkedList or iterate() sources, ordered operations like limit and findFirst, and shared mutable state. In a web server they compete for the same common pool, so measure before using them.
18

You need to process a 5 GB file using streams without running out of memory. How?

Save to ▾
Show answer
Use Files.lines(path), which reads lazily line by line, inside try-with-resources. Apply filter and map, then aggregate with a collector that keeps small results such as counts or sums instead of collecting all lines into a list. If the output is large, write it incrementally to a BufferedWriter. Avoid sorted() and distinct() on huge data because they buffer everything.
19

A thread pool fills up and tasks get rejected during traffic spikes. How do you handle it?

Save to ▾
Show answer
First check why tasks are slow, since slow tasks fill pools. Then choose a policy: a bounded queue with CallerRunsPolicy applies backpressure by running the task in the submitting thread; otherwise return a fast 503 so clients retry. Tune pool and queue sizes from load tests. Never use an unbounded queue, because it hides the problem until memory runs out.
20

Is it good practice to catch Exception or Throwable?

Save to ▾
Show answer
Usually no. Catching Throwable also catches Errors like OutOfMemoryError that the app cannot recover from, and catching Exception hides bugs by treating all failures the same. Catch the most specific exceptions you can handle. A broad catch is acceptable only at a top boundary, such as a global handler or thread entry point, where you log and return a safe error.
21

What are sealed classes and how do they help?

Save to ▾
Show answer
Sealed classes and interfaces, final in Java 17, restrict which classes can extend them using the permits clause, for example sealed interface Shape permits Circle, Square. Each subclass must be final, sealed or non-sealed. This models a closed set of types, and with pattern matching for switch in Java 21 the compiler can check that every case is handled without a default branch.
22

What is a deadlock and how can it be prevented?

Save to ▾
Show answer
A deadlock happens when two or more threads each hold a lock and wait for a lock held by the other, so none can continue. It needs mutual exclusion, hold and wait, no preemption and circular wait. Prevent it by always acquiring locks in the same global order, using tryLock with a timeout, holding locks briefly and avoiding calls to unknown code while holding a lock.
23

What is the difference between synchronized and ReentrantLock?

Save to ▾
Show answer
synchronized is a built-in keyword that locks a monitor and releases it automatically at block exit. ReentrantLock is an explicit lock that adds tryLock with timeout, interruptible locking, fairness options and multiple Condition objects, but you must unlock in a finally block. Both are reentrant. Prefer synchronized for simple cases and ReentrantLock when you need its extra features.
24

What is CompletableFuture and how is it better than Future?

Save to ▾
Show answer
Future only lets you block with get() to obtain a result. CompletableFuture supports non-blocking composition: thenApply to transform, thenCompose to chain async calls, thenCombine or allOf to join several, and exceptionally or handle for errors. It runs on the common ForkJoinPool by default, but pass your own executor for blocking I/O to avoid starving the pool.
25

Tell me about a time you improved performance by choosing a better data structure.

Save to ▾
Show answer
Situation: a report job matching 2 lakh transactions to customers took 40 minutes. Task: bring it under the 5 minute window. Action: profiling showed list.contains() inside a loop, which was O(n squared). I loaded customer ids into a HashSet and grouped transactions with a HashMap. Result: runtime dropped to 50 seconds and I shared the pattern in our team wiki.
26

Add optimistic locking to an entity and handle the conflict.

Save to ▾
Show answer
Add a version field; Hibernate checks it on update. @Entity class Account { @Id Long id; long balance; @Version Long version; } @Retryable(retryFor = ObjectOptimisticLockingFailureException.class, maxAttempts = 3) @Transactional public void debit(Long id, long amt) { Account a = repo.findById(id).orElseThrow(); a.balance -= amt; } The update includes WHERE version = ?, so a stale write fails and is retried.
27

What is the difference between reduce() and collect()?

Save to ▾
Show answer
reduce() combines elements into a single immutable value using an identity and an associative function, such as summing numbers. collect() is a mutable reduction that accumulates into a container like a List, Map or StringBuilder, which is far more efficient for building collections. Using reduce to build a list creates many intermediate copies, so use collect for containers.
28

Write a thread safe singleton class in Java.

Save to ▾
Show answer
The simplest safe options are an enum or the holder idiom. public class Config { private Config() {} private static class Holder { static final Config INSTANCE = new Config(); } public static Config getInstance() { return Holder.INSTANCE; } } The JVM loads Holder lazily and class initialisation is thread safe. An enum singleton also resists reflection and serialization attacks.
29

You need a cache that evicts the least recently used item when full. How would you build it in Java?

Save to ▾
Show answer
Extend LinkedHashMap with accessOrder set to true and override removeEldestEntry to return true when size exceeds capacity. Each get moves the entry to the end, so the eldest is the least recently used. It is not thread safe, so wrap it with synchronization for shared use. In production prefer Caffeine, which offers size and time based eviction with high concurrency.
30

How would you write a simple thread safe rate limiter in Java?

Save to ▾
Show answer
A token bucket with synchronized refill is simple and correct. class RateLimiter { private final long capacity, refillPerSec; private double tokens; private long last = System.nanoTime(); RateLimiter(long cap, long rps) { capacity = cap; refillPerSec = rps; tokens = cap; } synchronized boolean tryAcquire() { long now = System.nanoTime(); tokens = Math.min(capacity, tokens + (now - last) / 1e9 * refillPerSec); last = now; if (tokens >= 1) { tokens--; return true; } return false; } } Across servers, keep the bucket in Redis.
31

What is the difference between JPA, Hibernate and Spring Data JPA?

Save to ▾
Show answer
JPA, now Jakarta Persistence, is a specification of interfaces and annotations for object relational mapping. Hibernate is the most popular implementation of that specification and adds its own features. Spring Data JPA sits on top and generates repository implementations from interfaces and method names like findByEmail, reducing boilerplate. Your code uses JPA annotations, Hibernate does the work and Spring Data simplifies access.
32

What are transaction isolation levels and which problems do they prevent?

Save to ▾
Show answer
Read Uncommitted allows dirty reads. Read Committed prevents dirty reads and is the default in PostgreSQL and SQL Server. Repeatable Read also prevents non-repeatable reads and is the MySQL InnoDB default. Serializable prevents phantom reads too but reduces concurrency. Choose the lowest level that keeps data correct, and use explicit locking for specific hot rows.
33

Write a Spring Data JPA repository method that fetches orders with items to avoid N+1.

Save to ▾
Show answer
Use JOIN FETCH or an entity graph. public interface OrderRepository extends JpaRepository<Order, Long> { @Query("select distinct o from Order o join fetch o.items where o.customerId = :cid") List<Order> findWithItems(@Param("cid") Long customerId); @EntityGraph(attributePaths = "items") List<Order> findByStatus(String status); } Both load orders and items in one query.
34

toMap() throws Duplicate key exception in production. How do you fix it?

Save to ▾
Show answer
The data has repeated keys that the developer assumed were unique. Decide the business rule, then pass a merge function, for example toMap(User::email, u -> u, (a, b) -> a) to keep the first, or use groupingBy if all values are needed. Also check upstream data quality, since duplicates may signal a deeper bug such as missing unique constraints.
35

Configure a Resilience4j circuit breaker on a client call in Spring Boot.

Save to ▾
Show answer
Annotate the method and provide a fallback. @CircuitBreaker(name = "inventory", fallbackMethod = "stockUnknown") public Stock check(String sku) { return restClient.get().uri("/stock/{sku}", sku) .retrieve().body(Stock.class); } private Stock stockUnknown(String sku, Throwable t) { return Stock.unknown(sku); } # application.yml resilience4j.circuitbreaker.instances.inventory: failure-rate-threshold: 50 wait-duration-in-open-state: 10s
36

What is the first level and second level cache in Hibernate?

Save to ▾
Show answer
The first level cache is the persistence context itself; it is per session or EntityManager, always on, and returns the same object for repeated finds by id in one transaction. The second level cache is shared across sessions and optional, backed by providers like Ehcache or Infinispan through JCache. Use it for read-mostly reference data, and be careful about stale data in clustered setups.
37

Group a list of orders by city and sum the amount per city.

Save to ▾
Show answer
Use groupingBy with a summing collector. Map<String, Double> totals = orders.stream() .collect(Collectors.groupingBy( Order::city, TreeMap::new, Collectors.summingDouble(Order::amount))); TreeMap keeps cities sorted. For money, store amounts as long paise or BigDecimal and use Collectors.reducing with BigDecimal::add.
38

Two users booking the last seat both succeed. How do you prevent double booking?

Save to ▾
Show answer
This is a race between read and write. Use a database guarantee: a unique constraint on seat and show, an atomic conditional update like UPDATE seats SET status = 'BOOKED' WHERE id = ? AND status = 'FREE' and check the affected row count, or pessimistic locking with SELECT FOR UPDATE. Optimistic locking with a version column also works, retrying or failing the loser.
39

A query is fast in development but takes 8 seconds in production. How do you investigate?

Save to ▾
Show answer
Production has more data, so check the execution plan with EXPLAIN ANALYZE on production-like data. Look for full table scans, missing indexes on filter or join columns, functions on indexed columns and poor statistics. Check if Hibernate generates the SQL you expect. Add a suitable composite index, rewrite the query or paginate, and verify the plan improves before release.
40

A HashMap shared by many threads sometimes loses updates. How do you fix it?

Save to ▾
Show answer
HashMap is not thread safe, so concurrent put calls can overwrite each other. Replace it with ConcurrentHashMap and use atomic methods instead of get-then-put, for example counts.merge(key, 1, Integer::sum) or computeIfAbsent for lazy creation. Collections.synchronizedMap also works but locks the whole map, which hurts throughput under contention.

Frequently asked questions

What is asked in Java interviews for 5 years of experience?

At five years, interviews include system design: scalable APIs, database choices, caching, messaging, consistency and failure handling. Interviewers expect JVM and GC tuning knowledge, deep concurrency, and stories of leading features, mentoring juniors and handling incidents. Coding rounds still appear, but design depth and trade-off discussions carry more weight. Expect questions on code review and estimation too.

How many questions should I practise before a Java interview?

Work through all 40 questions here, then the company-wise sets for the employers you are targeting. Quality matters more than count: be able to explain why each answer is right.

Which topics matter most for 5 years of experience?

Focus first on System design, JVM and GC tuning, Distributed system patterns, Technical leadership.