Interview questions · Tech stack

Java Coding Interview Questions & Answers (2026)

These interviews test core Java fundamentals, algorithmic thinking, and problem‑solving under time pressure. Success comes from mastering language nuances, writing clean, efficient code, and clearly explaining trade‑offs. Focus on data structures, concurrency, and performance patterns, then practice explaining your solution step‑by‑step to demonstrate depth and communication skills.

20 questions · updated Aug 29, 2026

Quick facts

Typical roundsPhone screen, live coding, system design, and final on‑site
Common focusArrays, strings, collections, concurrency, and Java 8 streams
Time per problem30–45 minutes for coding, 10–15 minutes for explanation
Success metricCorrectness, optimality, readability, and clear reasoning

Questions

Beginner

Reverse a string in Java without using StringBuilder.

Iterate from the end of the char array, building a new char[] and converting back to a String. This shows manual handling of immutability and O(n) time with O(n) extra space. An interviewer expects you to discuss why StringBuilder is usually preferred for readability, but the manual approach proves you understand underlying mechanics and can control memory usage when needed.

char[] chars = s.toCharArray();
char[] rev = new char[chars.length];
for (int i = 0; i < chars.length; i++) {
    rev[i] = chars[chars.length - 1 - i];
}
return new String(rev);
GoogleAmazonMicrosoft

Find the first non‑repeated character in a string.

Use a LinkedHashMap<Character, Integer> to preserve insertion order while counting occurrences. After one pass to fill counts, iterate the map to return the first key with value 1. This demonstrates knowledge of collection ordering, O(n) time, and O(k) space where k is distinct characters. Explain trade‑offs versus two‑pass array counting for ASCII strings.

Map<Character, Integer> map = new LinkedHashMap<>();
for (char c : s.toCharArray()) {
    map.put(c, map.getOrDefault(c, 0) + 1);
}
for (Map.Entry<Character, Integer> e : map.entrySet()) {
    if (e.getValue() == 1) return e.getKey();
}
return null;
NetflixAdobe

Implement a function to check if a linked list has a cycle.

Apply Floyd’s Tortoise and Hare algorithm: two pointers move at different speeds; if they meet, a cycle exists. This runs in O(n) time and O(1) space, showing you understand pointer manipulation and edge cases like single‑node lists. Mention that a HashSet could also detect cycles but uses extra memory.

ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
    slow = slow.next;
    fast = fast.next.next;
    if (slow == fast) return true;
}
return false;
GoogleFacebook

Write a method to merge two sorted integer arrays into a new sorted array.

Use two indices, compare elements, and copy the smaller one into the result array, advancing the corresponding index. Continue until one array is exhausted, then copy the remainder. This yields O(m+n) time and O(m+n) space, demonstrating ability to work with array boundaries and avoid off‑by‑one errors.

int[] result = new int[a.length + b.length];
int i=0,j=0,k=0;
while(i<a.length && j<b.length) {
    result[k++] = a[i] <= b[j] ? a[i++] : b[j++];
}
while(i<a.length) result[k++] = a[i++];
while(j<b.length) result[k++] = b[j++];
return result;
Amazon

Explain the difference between == and .equals() for Java objects.

The == operator checks reference identity—whether two variables point to the exact same object in memory. .equals() is a method that can be overridden to compare logical state; for strings it compares character sequences, for custom classes you define what equality means. Interviewers look for awareness of default Object.equals() behavior and the importance of overriding hashCode when equals is overridden.

What is autoboxing and when can it cause performance issues?

Autoboxing automatically converts between primitive types and their wrapper classes (e.g., int ↔ Integer). It can cause performance hits due to extra object allocation and garbage collection, especially inside tight loops or when using collections of primitives. A strong candidate mentions avoiding unnecessary boxing, using primitive streams, or third‑party libraries like fastutil for high‑throughput scenarios.

Intermediate

Implement a function to find the kth largest element in an unsorted array.

Use a min‑heap of size k (PriorityQueue<Integer>) to keep the k largest elements seen so far. Iterate the array, adding each element and removing the smallest when size exceeds k. After processing, the heap root is the kth largest. This runs in O(n log k) time and O(k) space, showing you can balance time‑space trade‑offs versus sorting the whole array.

PriorityQueue<Integer> heap = new PriorityQueue<>();
for (int num : nums) {
    heap.offer(num);
    if (heap.size() > k) heap.poll();
}
return heap.peek();
MicrosoftUber

Explain how Java’s HashMap handles collisions.

HashMap first computes a bucket index from the key’s hashCode. If multiple keys map to the same bucket, they are stored in a linked list (Java 7) or a balanced tree (Java 8+) once the list exceeds a threshold (8 entries). This hybrid approach keeps average O(1) lookup while guaranteeing O(log n) worst‑case when many collisions occur, demonstrating knowledge of internal optimizations.

Write a method to perform a level‑order traversal of a binary tree.

Use a Queue<TreeNode> to process nodes breadth‑first. Enqueue the root, then repeatedly dequeue a node, add its value to the result, and enqueue its non‑null children. This yields O(n) time and O(w) space where w is the maximum width. Explain why recursion (DFS) would not preserve level order without extra bookkeeping.

List<Integer> result = new ArrayList<>();
Queue<TreeNode> q = new LinkedList<>();
if (root != null) q.offer(root);
while (!q.isEmpty()) {
    TreeNode node = q.poll();
    result.add(node.val);
    if (node.left != null) q.offer(node.left);
    if (node.right != null) q.offer(node.right);
}
return result;
Google

How does the Java Memory Model ensure visibility of changes across threads?

The JMM defines happens‑before relationships. Writes to a volatile variable, lock releases, and thread start/join create happens‑before edges that guarantee other threads see the latest values. Without these, caches could hide updates. Interviewers expect you to mention volatile, synchronized blocks, and atomic classes as tools to enforce visibility and ordering.

Implement a function to find the longest palindrome substring.

Use expand‑around‑center technique: for each index, expand left and right for odd and even length palindromes, tracking the longest found. This runs in O(n^2) time and O(1) space, which is acceptable for interview constraints. Discuss why Manacher’s algorithm can achieve O(n) but is rarely required unless explicitly asked.

int start=0, end=0;
for (int i=0;i<s.length();i++) {
    int len1 = expand(s,i,i);
    int len2 = expand(s,i,i+1);
    int len = Math.max(len1,len2);
    if (len>end-start) {
        start = i-(len-1)/2;
        end = i+len/2;
    }
}
return s.substring(start,end+1);
private int expand(String s,int l,int r){
    while(l>=0 && r<s.length() && s.charAt(l)==s.charAt(r)) {l--;r++;}
    return r-l-1;
}
AmazonNetflix

Explain the difference between fail‑fast and fail‑safe iterators in Java collections.

Fail‑fast iterators (e.g., those from ArrayList, HashMap) detect concurrent modification and throw ConcurrentModificationException, protecting against inconsistent state. Fail‑safe iterators (e.g., from ConcurrentHashMap, CopyOnWriteArrayList) operate on a snapshot or use internal locking, allowing modifications without exception but possibly returning stale data. Interviewers look for awareness of concurrency implications and appropriate collection choice.

Write a method to compute the nth Fibonacci number using memoization.

Create an int[] memo initialized with -1. Recursive helper checks memo[n]; if -1, compute fib(n‑1)+fib(n‑2) and store. This reduces exponential recursion to O(n) time and O(n) space. Explain why plain recursion is inefficient and how memoization leverages dynamic programming to meet interview performance expectations.

int[] memo = new int[n+1];
Arrays.fill(memo,-1);
return fib(n,memo);
private int fib(int i,int[] memo){
    if(i<=1) return i;
    if(memo[i]!=-1) return memo[i];
    memo[i]=fib(i-1,memo)+fib(i-2,memo);
    return memo[i];
}
Facebook

Advanced

Describe how the Java Stream API processes pipelines lazily.

Intermediate operations (map, filter, sorted) are lazy; they build a pipeline of Supplier functions without executing. A terminal operation (collect, forEach) triggers traversal, pulling elements through the pipeline one at a time. This enables short‑circuiting and reduces intermediate collection creation. Interviewers expect you to discuss spliterator characteristics and how parallel streams split work while preserving order when required.

Implement a thread‑safe bounded blocking queue using ReentrantLock and Condition.

Maintain an array buffer, head/tail indices, and count. Use a ReentrantLock for mutual exclusion. Two Conditions, notFull and notEmpty, manage waiting producers and consumers. put() waits while count == capacity, then inserts and signals notEmpty; take() waits while count == 0, then removes and signals notFull. This demonstrates mastery of low‑level concurrency primitives and avoids spurious wake‑ups.

class BoundedQueue<T>{
    private final T[] items;
    private int head, tail, count;
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();
    BoundedQueue(int capacity){items=(T[])new Object[capacity];}
    void put(T x) throws InterruptedException{lock.lock();try{while(count==items.length) notFull.await();items[tail]=x;tail=(tail+1)%items.length;count++;notEmpty.signal();}finally{lock.unlock();}}
    T take() throws InterruptedException{lock.lock();try{while(count==0) notEmpty.await();T x=items[head];head=(head+1)%items.length;count--;notFull.signal();return x;}finally{lock.unlock();}}
}
GoogleAmazon

What is the Java Memory Model’s guarantee for final fields?

Final fields have a special happens‑before guarantee: once the constructor finishes, any thread that sees the constructed object is guaranteed to see the correctly initialized final fields without additional synchronization. This enables safe publication of immutable objects. Interviewers look for this nuance to differentiate between normal fields and final fields in concurrency contexts.

Explain how the Fork/Join framework achieves work‑stealing.

Each ForkJoinPool worker thread maintains a double‑ended deque. When a task forks, it pushes subtasks onto its own deque. Idle workers steal tasks from the tail of other workers’ deques, preserving locality for the owner (LIFO) while providing load balancing (FIFO stealing). This reduces contention and improves parallelism for divide‑and‑conquer algorithms.

Netflix

Write a method to detect if a string is a valid number according to Java’s Double.parseDouble rules.

Use a regular expression that matches optional sign, digits, optional decimal point with fraction, optional exponent part, and optional type suffix. This mirrors Double.parseDouble’s grammar without invoking the parser, demonstrating knowledge of numeric literal specifications and edge cases like "NaN" or "Infinity".

String regex = "[+-]?((\d+\.\d*)|(\.\d+)|(\d+))( [eE][+-]?\d+)?[fFdD]?|[+-]?(NaN|Infinity)";
return s.matches(regex);
Microsoft

How does Java 8’s CompletableFuture differ from Future?

CompletableFuture supports non‑blocking composition via thenApply, thenCombine, and exceptionally, enabling pipelines of asynchronous tasks. It can be manually completed, cancelled, or combined, whereas Future only provides get() blocking retrieval and limited cancellation. Interviewers expect you to discuss async callbacks, exception propagation, and the advantage of avoiding thread‑blocking.

Implement a method to find all permutations of a string.

Use backtracking: swap each character with the current index, recurse for the next position, then backtrack by swapping back. Store results in a List<String>. This yields O(n·n!) time and O(n) recursion stack, showcasing depth‑first exploration and careful handling of duplicate characters by using a Set at each recursion level.

void permute(char[] arr,int l,List<String> res){
    if(l==arr.length) {res.add(new String(arr));return;}
    Set<Character> seen=new HashSet<>();
    for(int i=l;i<arr.length;i++){
        if(seen.add(arr[i])){
            swap(arr,l,i);
            permute(arr,l+1,res);
            swap(arr,l,i);
        }
    }
}
private void swap(char[] a,int i,int j){char t=a[i];a[i]=a[j];a[j]=t;}
GoogleFacebook

Common mistakes

  • Using System.out.println for debugging instead of proper logging, which obscures performance impact.
  • Neglecting edge cases such as empty inputs, null values, or single‑element collections.
  • Choosing O(n²) solutions when O(n log n) or O(n) alternatives exist, showing lack of algorithmic optimization.
  • Failing to explain time and space complexity, leaving interviewers uncertain about trade‑offs.
  • Mixing up reference equality (==) with logical equality (.equals()) in collections.

Study plan

  1. Review core Java syntax, data structures, and common library classes for 2 days.
  2. Solve 30+ coding problems covering arrays, strings, and linked lists; focus on writing clean code.
  3. Practice concurrency concepts and Java 8 streams for 1 day, including hands‑on mini‑projects.
  4. Mock interview with timed coding sessions; record explanations and refine communication.
  5. Review system design basics and be ready to discuss scalability trade‑offs for 1 day.

FAQ

How many coding questions are typically asked in a Java interview?

Most companies ask 2–3 coding problems per interview round, with a mix of easy and medium difficulty. On‑site days may include an additional whiteboard challenge, bringing the total to 4–5 across the full process.

Should I use Java 8 features like streams in my solutions?

Yes, if you can write them clearly. Streams show modern proficiency, but be ready to fall back to loops if the interviewer asks for step‑by‑step reasoning or performance details.

What is the best way to handle recursion depth limits?

Explain tail‑recursion optimization (which Java does not perform) and suggest converting to an iterative solution with an explicit stack when depth could exceed the call stack limit.

How important is Big‑O analysis in coding interviews?

Very important. Interviewers expect you to state time and space complexity for every solution, compare alternatives, and justify why your approach meets the problem constraints.

Can I ask clarifying questions before coding?

Absolutely. Clarifying input constraints, expected output format, and edge cases demonstrates thoroughness and often leads to a more focused solution.

Related

Ready for your next interview?

Download MiPrep AI. Load your resume and the job description. Show up ready.

Free tier · No credit card · macOS 14+ · Windows 10+

Free tier · No credit card · Runs on your Mac or Windows machine