top of page

The Ultimate Java Interview Questions Guide 2025 : Part-4

Q55: Implement a simple LRU (Least Recently Used) Cache.

import java.util.*;

public class LRUCache<KV> {
    private final int capacity;
    private final Map<KNode<KV>> cache;
    private final Node<KV> head;
    private final Node<KV> tail;
    
    private static class Node<KV> {
        K key;
        V value;
        Node<KV> prev;
        Node<KV> 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<KV> 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<KV> node = cache.get(key);
        
        if (node != null) {
            // Update existing node
            node.value = value;
            moveToHead(node);
        } else {
            // Add new node
            Node<KV> newNode = new Node<>(key, value);
            
            if (cache.size() >= capacity) {
                // Remove least recently used (tail)
                Node<KV> lastNode = removeTail();
                cache.remove(lastNode.key);
            }
            
            cache.put(key, newNode);
            addToHead(newNode);
        }
    }
    
    private void addToHead(Node<KV> node) {
        node.prev = head;
        node.next = head.next;
        head.next.prev = node;
        head.next = node;
    }
    
    private void removeNode(Node<KV> node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }
    
    private void moveToHead(Node<KV> node) {
        removeNode(node);
        addToHead(node);
    }
    
    private Node<KV> removeTail() {
        Node<KV> lastNode = tail.prev;
        removeNode(lastNode);
        return lastNode;
    }
    
    public int size() {
        return cache.size();
    }
    
    public void printCache() {
        Node<KV> 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<IntegerString> 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<StringWeakReference<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<EventListenerObject> 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<StringString> 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<StringString> 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<StringString> 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

  1. LeetCode: Algorithm and data structure problems

  2. HackerRank: Java-specific challenges

  3. CodeSignal: Technical assessments

  4. Pramp: Mock interview practice

  5. 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:

  1. Explain the difference between == and .equals()

  2. What is method overloading vs overriding?

  3. How do you handle exceptions in Java?

  4. What are the different access modifiers?

  5. Explain ArrayList vs LinkedList

  6. Write a program to reverse a string

  7. What is inheritance? Provide an example

  8. How do you create a thread in Java?

  9. What is the purpose of static keyword?

  10. 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:

  1. Explain HashMap internal working

  2. What is the difference between fail-fast and fail-safe iterators?

  3. How does garbage collection work in Java?

  4. Explain different types of memory areas in JVM

  5. What is the difference between synchronized and volatile?

  6. How do you prevent deadlocks?

  7. Explain lambda expressions and functional interfaces

  8. What is the purpose of Stream API?

  9. How do you implement Singleton pattern thread-safely?

  10. 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:

  1. How would you design a distributed caching system?

  2. Explain different garbage collection algorithms

  3. How do you optimize JVM performance?

  4. Design a URL shortening service

  5. How do you handle million concurrent requests?

  6. Explain microservices architecture challenges

  7. How do you ensure data consistency in distributed systems?

  8. Design a real-time chat system

  9. How do you implement circuit breaker pattern?

  10. 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

  1. Not knowing basic concepts: Unable to explain fundamental OOP principles

  2. Poor coding practices: Not following naming conventions, no error handling

  3. Memory management ignorance: Not understanding when objects are eligible for GC

  4. No testing knowledge: Unable to write or discuss unit tests

  5. Framework dependency: Only knowing frameworks without understanding underlying concepts

Behavioral Red Flags

  1. Overconfidence: Claiming to know everything without admitting knowledge gaps

  2. Poor communication: Unable to explain technical concepts clearly

  3. No questions: Not asking any questions about the role or company

  4. Negative attitude: Speaking poorly about previous employers or technologies

  5. Lack of curiosity: No interest in learning new technologies or improving skills

Last-Minute Interview Tips

Day Before Interview

  1. Review your resume: Be ready to explain every technology and project mentioned

  2. Practice coding: Solve 2-3 medium-level problems on paper

  3. Prepare questions: Have thoughtful questions ready for the interviewer

  4. Plan logistics: Know the route, parking, dress code

  5. Get good sleep: Rest well to stay sharp during the interview

During the Interview

  1. Think out loud: Explain your thought process while solving problems

  2. Ask clarifying questions: Don't assume requirements, ask for clarification

  3. Start with simple solution: Get a working solution first, then optimize

  4. Test your code: Walk through your solution with example inputs

  5. Be honest: Admit when you don't know something and explain how you'd find out

After the Interview

  1. Send thank you note: Email within 24 hours thanking the interviewer

  2. Reflect and learn: Note down questions you struggled with for future study

  3. Follow up appropriately: Respect the timeline given by the interviewer

  4. Continue learning: Keep improving regardless of the outcome

Additional Resources

Essential Books

  1. "Effective Java" by Joshua Bloch: Best practices and advanced techniques

  2. "Java Concurrency in Practice" by Brian Goetz: Comprehensive concurrency guide

  3. "Clean Code" by Robert Martin: Writing maintainable code

  4. "System Design Interview" by Alex Xu: System design fundamentals

  5. "Cracking the Coding Interview" by Gayle McDowell: Interview preparation

Online Resources

  1. Oracle Java Documentation: Official Java documentation

  2. 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:

  1. Master the fundamentals before moving to advanced topics

  2. Practice coding regularly on platforms like LeetCode and HackerRank

  3. Understand the 'why' behind concepts, not just the 'what'

  4. Stay updated with latest Java features and industry trends

  5. Practice system design for senior-level positions

  6. Develop soft skills alongside technical knowledge

  7. 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!

Related Posts

See All

Comments


bottom of page