The Ultimate Java Interview Questions Guide 2025 : Part-4
- Sujeet Prajapati

- Aug 20
- 13 min read
Q55: Implement a simple LRU (Least Recently Used) Cache.
import java.util.*;
public class LRUCache<K, V> {
private final int capacity;
private final Map<K, Node<K, V>> cache;
private final Node<K, V> head;
private final Node<K, V> tail;
private static class Node<K, V> {
K key;
V value;
Node<K, V> prev;
Node<K, V> next;
Node(K key, V value) {
this.key = key;
this.value = value;
}
}
public LRUCache(int capacity) {
this.capacity = capacity;
this.cache = new HashMap<>();
// Create dummy head and tail nodes
this.head = new Node<>(null, null);
this.tail = new Node<>(null, null);
head.next = tail;
tail.prev = head;
}
public V get(K key) {
Node<K, V> node = cache.get(key);
if (node == null) {
return null;
}
// Move to head (most recently used)
moveToHead(node);
return node.value;
}
public void put(K key, V value) {
Node<K, V> node = cache.get(key);
if (node != null) {
// Update existing node
node.value = value;
moveToHead(node);
} else {
// Add new node
Node<K, V> newNode = new Node<>(key, value);
if (cache.size() >= capacity) {
// Remove least recently used (tail)
Node<K, V> lastNode = removeTail();
cache.remove(lastNode.key);
}
cache.put(key, newNode);
addToHead(newNode);
}
}
private void addToHead(Node<K, V> node) {
node.prev = head;
node.next = head.next;
head.next.prev = node;
head.next = node;
}
private void removeNode(Node<K, V> node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void moveToHead(Node<K, V> node) {
removeNode(node);
addToHead(node);
}
private Node<K, V> removeTail() {
Node<K, V> lastNode = tail.prev;
removeNode(lastNode);
return lastNode;
}
public int size() {
return cache.size();
}
public void printCache() {
Node<K, V> current = head.next;
System.out.print("Cache (MRU to LRU): ");
while (current != tail) {
System.out.print(current.key + "=" + current.value + " ");
current = current.next;
}
System.out.println();
}
public static void main(String[] args) {
LRUCache<Integer, String> cache = new LRUCache<>(3);
cache.put(1, "One");
cache.put(2, "Two");
cache.put(3, "Three");
cache.printCache(); // 3=Three 2=Two 1=One
cache.get(1); // Access 1
cache.printCache(); // 1=One 3=Three 2=Two
cache.put(4, "Four"); // Evicts 2
cache.printCache(); // 4=Four 1=One 3=Three
}
}System Design and Architecture Questions
Q56: How would you design a URL shortener like bit.ly?
High-Level Design:
// Domain models
public class Url {
private String originalUrl;
private String shortCode;
private LocalDateTime createdAt;
private LocalDateTime expiresAt;
private long clickCount;
private String userId;
// Constructors, getters, setters
}
// Service layer
@Service
public class UrlShortenerService {
private final UrlRepository urlRepository;
private final Base62Encoder encoder;
private final CacheService cacheService;
public String shortenUrl(String originalUrl, String userId) {
// Check if URL already exists
Optional<Url> existing = urlRepository.findByOriginalUrl(originalUrl);
if (existing.isPresent()) {
return existing.get().getShortCode();
}
// Generate unique short code
String shortCode = generateShortCode();
// Save to database
Url url = new Url();
url.setOriginalUrl(originalUrl);
url.setShortCode(shortCode);
url.setUserId(userId);
url.setCreatedAt(LocalDateTime.now());
url.setExpiresAt(LocalDateTime.now().plusYears(1));
urlRepository.save(url);
// Cache for quick access
cacheService.put(shortCode, originalUrl);
return shortCode;
}
public String expandUrl(String shortCode) {
// Try cache first
String cachedUrl = cacheService.get(shortCode);
if (cachedUrl != null) {
incrementClickCount(shortCode);
return cachedUrl;
}
// Fallback to database
Optional<Url> url = urlRepository.findByShortCode(shortCode);
if (url.isPresent() && !isExpired(url.get())) {
String originalUrl = url.get().getOriginalUrl();
cacheService.put(shortCode, originalUrl);
incrementClickCount(shortCode);
return originalUrl;
}
throw new UrlNotFoundException("Short URL not found or expired");
}
private String generateShortCode() {
// Use distributed ID generator or database sequence
long id = idGenerator.generateId();
return encoder.encode(id);
}
private void incrementClickCount(String shortCode) {
// Async update to avoid blocking
CompletableFuture.runAsync(() ->
urlRepository.incrementClickCount(shortCode));
}
}
// Base62 encoder for short codes
@Component
public class Base62Encoder {
private static final String ALPHABET =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
private static final int BASE = ALPHABET.length();
public String encode(long id) {
StringBuilder sb = new StringBuilder();
while (id > 0) {
sb.append(ALPHABET.charAt((int) (id % BASE)));
id /= BASE;
}
return sb.reverse().toString();
}
public long decode(String shortCode) {
long id = 0;
for (char c : shortCode.toCharArray()) {
id = id * BASE + ALPHABET.indexOf(c);
}
return id;
}
}Key Design Considerations:
Scalability: Distributed database, caching, load balancing
Performance: Cache frequently accessed URLs, async operations
Reliability: Database replication, backup strategies
Security: Rate limiting, spam detection, malicious URL filtering
Analytics: Click tracking, geographical data, referrer information
Performance and Optimization
Q57: How do you identify and fix memory leaks in Java applications?
Common Causes and Solutions:
// 1. Static collections - memory leak
public class MemoryLeakExample {
private static List<Object> cache = new ArrayList<>();
public void addToCache(Object obj) {
cache.add(obj); // Objects never removed
}
// Fix: Provide removal method and use weak references
private static Map<String, WeakReference<Object>> weakCache =
new ConcurrentHashMap<>();
public void addToWeakCache(String key, Object obj) {
weakCache.put(key, new WeakReference<>(obj));
}
}
// 2. Listeners not removed - memory leak
public class EventPublisher {
private List<EventListener> listeners = new ArrayList<>();
public void addListener(EventListener listener) {
listeners.add(listener);
}
// Fix: Always provide removal method
public void removeListener(EventListener listener) {
listeners.remove(listener);
}
// Or use WeakHashMap for automatic cleanup
private Map<EventListener, Object> listenerMap = new WeakHashMap<>();
}
// 3. Unclosed resources - memory leak
public class ResourceLeak {
public void readFile() throws IOException {
FileInputStream fis = new FileInputStream("file.txt");
// File not closed - potential leak
}
// Fix: Use try-with-resources
public void readFileCorrectly() throws IOException {
try (FileInputStream fis = new FileInputStream("file.txt")) {
// File automatically closed
}
}
}Tools for Memory Analysis:
JProfiler: Commercial profiler with memory analysis
VisualVM: Free profiler bundled with JDK
Eclipse MAT: Memory analyzer tool
JConsole: Basic JVM monitoring
GC Logs: Analyze garbage collection patterns
Best Practices and Tips
Q58: What are Java coding best practices?
1. Naming Conventions:
// Classes: PascalCase
public class UserService { }
// Methods and variables: camelCase
public void calculateTotalAmount() { }
private int itemCount;
// Constants: UPPER_CASE
public static final int MAX_RETRY_COUNT = 3;
// Packages: lowercase
package com.company.project.service;2. Error Handling:
// Use specific exceptions
public class UserService {
public User findUser(Long id) throws UserNotFoundException {
User user = userRepository.findById(id);
if (user == null) {
throw new UserNotFoundException("User not found with id: " + id);
}
return user;
}
// Don't catch generic Exception unless necessary
public void processData() {
try {
// risky operation
} catch (SpecificException e) {
// handle specific case
logger.error("Specific error occurred", e);
} catch (Exception e) {
// handle all other cases
logger.error("Unexpected error", e);
throw new ServiceException("Processing failed", e);
}
}
}3. Resource Management:
// Always use try-with-resources
public String readFile(String filename) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(Paths.get(filename))) {
return reader.lines().collect(Collectors.joining("\n"));
}
}
// Close resources in finally if try-with-resources not applicable
public void legacyResourceHandling() {
Connection connection = null;
try {
connection = dataSource.getConnection();
// use connection
} catch (SQLException e) {
logger.error("Database error", e);
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
logger.error("Error closing connection", e);
}
}
}
}4. Thread Safety:
// Use concurrent collections
private final Map<String, String> cache = new ConcurrentHashMap<>();
// Synchronize critical sections
public class Counter {
private int count = 0;
private final Object lock = new Object();
public void increment() {
synchronized (lock) {
count++;
}
}
// Or use atomic classes
private final AtomicInteger atomicCount = new AtomicInteger(0);
public void atomicIncrement() {
atomicCount.incrementAndGet();
}
}Q59: What are common performance optimization techniques?
1. Collection Optimization:
// Choose right collection type
Map<String, String> map = new HashMap<>(); // O(1) access
List<String> list = new ArrayList<>(); // O(1) access by index
Set<String> set = new HashSet<>(); // O(1) contains check
// Pre-size collections when possible
List<String> list = new ArrayList<>(expectedSize);
Map<String, String> map = new HashMap<>(expectedSize);
// Use StringBuilder for string concatenation
StringBuilder sb = new StringBuilder();
for (String item : items) {
sb.append(item).append(" ");
}
String result = sb.toString();2. Database Optimization:
// Use batch operations
@Transactional
public void batchInsert(List<User> users) {
int batchSize = 100;
for (int i = 0; i < users.size(); i += batchSize) {
List<User> batch = users.subList(i,
Math.min(i + batchSize, users.size()));
userRepository.saveAll(batch);
entityManager.flush();
entityManager.clear();
}
}
// Use pagination for large datasets
public Page<User> findUsers(int page, int size) {
Pageable pageable = PageRequest.of(page, size);
return userRepository.findAll(pageable);
}3. Caching:
@Service
public class UserService {
@Cacheable("users")
public User findUser(Long id) {
return userRepository.findById(id);
}
@CacheEvict("users")
public void updateUser(User user) {
userRepository.save(user);
}
}Final Tips for Java Interviews
Q60: What questions should you ask the interviewer?
Technical Questions:
What Java version and frameworks does the team use?
How do you handle code reviews and testing?
What are the biggest technical challenges the team faces?
How do you ensure code quality and maintainability?
Team and Process Questions:
What does a typical day look like for developers?
How does the team handle knowledge sharing?
What opportunities are there for learning and growth?
How do you measure success in this role?
Company Questions:
What are the company's technical goals for the next year?
How does technology contribute to the business strategy?
What's the career progression path for this role?
Interview Preparation Strategy
Study Timeline (4-6 Weeks)
Week 1-2: Core Java Fundamentals
Review OOP concepts, data types, and basic syntax
Practice basic coding problems
Understand collections framework thoroughly
Study exception handling and string manipulation
Week 3-4: Advanced Topics
Deep dive into multithreading and concurrency
Learn Java 8+ features (streams, lambdas, optional)
Understand memory management and garbage collection
Practice design patterns
Week 5-6: Framework and System Design
Study Spring Framework basics
Database concepts and JDBC
Practice system design questions
Mock interviews and coding challenges
Coding Practice Platforms
LeetCode: Algorithm and data structure problems
HackerRank: Java-specific challenges
CodeSignal: Technical assessments
Pramp: Mock interview practice
InterviewBit: Comprehensive interview preparation
Common Coding Patterns to Master
1. Two Pointers Pattern:
// Find pair with target sum in sorted array
public boolean hasTwoSum(int[] arr, int target) {
int left = 0, right = arr.length - 1;
while (left < right) {
int sum = arr[left] + arr[right];
if (sum == target) {
return true;
} else if (sum < target) {
left++;
} else {
right--;
}
}
return false;
}2. Sliding Window Pattern:
// Find maximum sum subarray of size k
public int maxSumSubarray(int[] arr, int k) {
int maxSum = 0, windowSum = 0;
// Calculate sum of first window
for (int i = 0; i < k; i++) {
windowSum += arr[i];
}
maxSum = windowSum;
// Slide the window
for (int i = k; i < arr.length; i++) {
windowSum = windowSum - arr[i - k] + arr[i];
maxSum = Math.max(maxSum, windowSum);
}
return maxSum;
}3. Fast and Slow Pointers (Floyd's Algorithm):
// Detect cycle in linked list
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast) {
if (fast == null || fast.next == null) {
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}4. Merge Intervals Pattern:
// Merge overlapping intervals
public int[][] merge(int[][] intervals) {
if (intervals.length <= 1) {
return intervals;
}
// Sort by start time
Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
List<int[]> result = new ArrayList<>();
int[] current = intervals[0];
for (int i = 1; i < intervals.length; i++) {
int[] next = intervals[i];
if (current[1] >= next[0]) {
// Overlapping, merge
current[1] = Math.max(current[1], next[1]);
} else {
// Non-overlapping, add current and move to next
result.add(current);
current = next;
}
}
result.add(current);
return result.toArray(new int[result.size()][]);
}Mock Interview Questions by Experience Level
Entry Level (0-2 Years)
Technical Questions:
Explain the difference between == and .equals()
What is method overloading vs overriding?
How do you handle exceptions in Java?
What are the different access modifiers?
Explain ArrayList vs LinkedList
Write a program to reverse a string
What is inheritance? Provide an example
How do you create a thread in Java?
What is the purpose of static keyword?
Explain try-with-resources
Coding Challenges:
Find the largest element in an array
Check if a string is a palindrome
Remove duplicates from an array
Count vowels in a string
Implement a simple calculator
Mid-Level (2-5 Years)
Technical Questions:
Explain HashMap internal working
What is the difference between fail-fast and fail-safe iterators?
How does garbage collection work in Java?
Explain different types of memory areas in JVM
What is the difference between synchronized and volatile?
How do you prevent deadlocks?
Explain lambda expressions and functional interfaces
What is the purpose of Stream API?
How do you implement Singleton pattern thread-safely?
Explain Spring dependency injection
Coding Challenges:
Implement LRU cache
Find intersection of two arrays
Design a thread-safe counter
Implement producer-consumer pattern
Binary tree traversal algorithms
Senior Level (5+ Years)
Technical Questions:
How would you design a distributed caching system?
Explain different garbage collection algorithms
How do you optimize JVM performance?
Design a URL shortening service
How do you handle million concurrent requests?
Explain microservices architecture challenges
How do you ensure data consistency in distributed systems?
Design a real-time chat system
How do you implement circuit breaker pattern?
Explain event-driven architecture
System Design Questions:
Design Twitter feed system
Design a payment processing system
Design a file storage system like Dropbox
Design a search engine
Design a recommendation system
Red Flags to Avoid in Interviews
Technical Red Flags
Not knowing basic concepts: Unable to explain fundamental OOP principles
Poor coding practices: Not following naming conventions, no error handling
Memory management ignorance: Not understanding when objects are eligible for GC
No testing knowledge: Unable to write or discuss unit tests
Framework dependency: Only knowing frameworks without understanding underlying concepts
Behavioral Red Flags
Overconfidence: Claiming to know everything without admitting knowledge gaps
Poor communication: Unable to explain technical concepts clearly
No questions: Not asking any questions about the role or company
Negative attitude: Speaking poorly about previous employers or technologies
Lack of curiosity: No interest in learning new technologies or improving skills
Last-Minute Interview Tips
Day Before Interview
Review your resume: Be ready to explain every technology and project mentioned
Practice coding: Solve 2-3 medium-level problems on paper
Prepare questions: Have thoughtful questions ready for the interviewer
Plan logistics: Know the route, parking, dress code
Get good sleep: Rest well to stay sharp during the interview
During the Interview
Think out loud: Explain your thought process while solving problems
Ask clarifying questions: Don't assume requirements, ask for clarification
Start with simple solution: Get a working solution first, then optimize
Test your code: Walk through your solution with example inputs
Be honest: Admit when you don't know something and explain how you'd find out
After the Interview
Send thank you note: Email within 24 hours thanking the interviewer
Reflect and learn: Note down questions you struggled with for future study
Follow up appropriately: Respect the timeline given by the interviewer
Continue learning: Keep improving regardless of the outcome
Additional Resources
Essential Books
"Effective Java" by Joshua Bloch: Best practices and advanced techniques
"Java Concurrency in Practice" by Brian Goetz: Comprehensive concurrency guide
"Clean Code" by Robert Martin: Writing maintainable code
"System Design Interview" by Alex Xu: System design fundamentals
"Cracking the Coding Interview" by Gayle McDowell: Interview preparation
Online Resources
Oracle Java Documentation: Official Java documentation
GitHub: Open source Java projects for learning
Conclusion
Java interviews can be challenging, but with proper preparation and practice, you can succeed. Remember these key points:
Master the fundamentals before moving to advanced topics
Practice coding regularly on platforms like LeetCode and HackerRank
Understand the 'why' behind concepts, not just the 'what'
Stay updated with latest Java features and industry trends
Practice system design for senior-level positions
Develop soft skills alongside technical knowledge
Learn from failures and keep improving
The Java ecosystem is vast and constantly evolving. Focus on building a strong foundation in core concepts, then expand your knowledge to frameworks and tools relevant to your target role. Remember that interviews are not just about technical knowledge – they also evaluate your problem-solving approach, communication skills, and cultural fit.
Good luck with your Java interviews! Remember, each interview is a learning opportunity that brings you closer to your goal. Stay confident, be genuine, and showcase your passion for Java development.
"The expert in anything was once a beginner." - Helen Hayes
Keep learning, keep practicing, and success will follow!


Comments