InterviewGrind Get notified

InterviewGrind › Java

Java Interview Questions and Answers

Equality, collections, overflow, switch fall-through and concurrency: Java interview questions drawn from production bugs, each with a clear explanation.

15 free questions from the app. Try each one before you open the answer.

1. ArithmeticEasy

The upload progress bar sits at 0% until the upload finishes. What fixes it?

int percent = done / total * 100;
  1. done / total * 100 → done * 100 / total
  2. int percent → double percent
  3. done / total * 100 → (done / total) * 100.0
  4. done / total → done % total
Show answer

Answer: A. done / total * 100 → done * 100 / total

With ints, done / total is 0 until done equals total. Multiply first so the division happens last, or divide as doubles: 100.0 * done / total.

2. StringsEasy

Admins sometimes get treated as regular users, depending on where the role string came from.

  1. boolean isAdmin(User u) {
  2. String role = u.getRole();
  3. if (role == "admin") {
  4. return true;
  5. }
  6. return false;
  7. }

Which line has the bug?

Show answer

Answer: Line 3: if (role == "admin") {

== compares object identity. A role read from a database or JSON is a different String object than the literal, so the check fails. Use "admin".equals(role), which is also null-safe.

3. Control flowEasy

Paid orders are being shipped and refunded.

  1. switch (status) {
  2. case PAID:
  3. ship(order);
  4. case CANCELLED:
  5. refund(order);
  6. break;
  7. default:
  8. hold(order);
  9. }

Which line has the bug?

Show answer

Answer: Line 3: ship(order);

Without a break after ship(order), execution falls through into the CANCELLED case. Add break;, or use arrow cases (case PAID -> ship(order);, Java 14+), which never fall through.

4. StringsEasy

Welcome emails say "Hi Ana null Lee" to people who have no middle name.

  1. String fullName(User u) {
  2. String first = u.getFirst();
  3. String last = u.getLast();
  4. return first + " " + u.getMiddle() + " " + last;
  5. }

Which line has the bug?

Show answer

Answer: Line 4: return first + " " + u.getMiddle() + " " + last;

String concatenation turns null into the text "null" instead of throwing. Join only the parts that exist, for example with a StringJoiner or by filtering nulls from a stream.

5. OverflowEasy

Total revenue in cents goes negative on big days. Change one word to fix it.

int totalCents = 0;
for (Order o : orders) totalCents += o.cents();
  1. int → long
  2. += → =
  3. for → while
  4. Add final
Show answer

Answer: A. int → long

An int tops out around $21.4 million in cents and then wraps negative. A long holds about 9.2 × 10¹⁸. For money, also consider Math.addExact to fail loudly instead of wrapping.

6. CollectionsEasy

You need a map whose keys come out in sorted order. Which do you pick, and what does it cost?

  1. HashMap: O(1) operations, sorted keys
  2. TreeMap: sorted keys, O(log n) operations
  3. LinkedHashMap: sorted keys, O(1) operations
  4. ArrayList of pairs: O(1) everything
Show answer

Answer: B. TreeMap: sorted keys, O(log n) operations

TreeMap is a red-black tree: keys stay sorted and you get firstKey, floorKey, range views and so on, at O(log n) per operation. HashMap is O(1) average with no order.

7. PerformanceEasy

Why use a StringBuilder instead of s += piece when building a long string in a loop?

  1. StringBuilder is thread-safe, so the loop can run in parallel
  2. Strings are immutable, so each += copies everything so far: O(n²)
  3. += creates a new variable each iteration, which the GC can't collect
  4. StringBuilder stores characters in less memory than String
Show answer

Answer: B. Strings are immutable, so each += copies everything so far: O(n²)

Every += creates a new String and copies the old contents. StringBuilder appends into a growable buffer, so the total work is linear.

8. ArraysEasy

The report's "before sorting" column shows the scores already sorted.

  1. int[] original = loadScores();
  2. int[] sorted = original;
  3. Arrays.sort(sorted);
  4. report(original, sorted);

Which line has the bug?

Show answer

Answer: Line 2: int[] sorted = original;

Assigning an array copies the reference, so both names point at one array and sorting one sorts both. Copy it: int[] sorted = original.clone(); (or Arrays.copyOf).

9. Static membersEasy

A brand-new customer's cart badge shows 37 items before they add anything.

  1. class Cart {
  2. private final List<Item> items = new ArrayList<>();
  3. static int itemCount = 0;
  4. void add(Item i) { items.add(i); itemCount++; }
  5. int size() { return itemCount; }
  6. }

Which line has the bug?

Show answer

Answer: Line 3: static int itemCount = 0;

static makes one counter shared by every Cart, so it counts items across all customers. Drop static, or better, return items.size() and skip the separate counter.

10. StringsEasy

Each email in the batch repeats the greetings of everyone before it. Why?

StringBuilder greeting = new StringBuilder();
for (User u : users) {
    greeting.append("Hi ").append(u.name());
    send(u, greeting.toString());
}
  1. One StringBuilder is shared by every iteration and never cleared
  2. toString() returns a live view that keeps changing after send runs
  3. append returns a new builder, so the old text is kept twice
  4. The for-each loop reuses the previous u, so names pile up
Show answer

Answer: A. One StringBuilder is shared by every iteration and never cleared

The builder is created once, so every append adds to the text from earlier users. Create it inside the loop, or call greeting.setLength(0) at the start of each iteration.

11. ArithmeticEasy

With 10 tasks and 3 workers, task 10 is never run. Why?

int perWorker = tasks.size() / workers;
for (int w = 0; w < workers; w++) {
    assign(w, tasks.subList(w * perWorker, (w + 1) * perWorker));
}
  1. 10 / 3 is 3 in int math, so only 9 tasks are handed out
  2. subList excludes its end index, so each worker loses one task
  3. The loop needs w <= workers so it reaches the last worker
  4. tasks.size() counts from zero, so it reports 9 tasks
Show answer

Answer: A. 10 / 3 is 3 in int math, so only 9 tasks are handed out

Integer division drops the remainder, so the leftover task is never assigned. Give the remainder to the last worker (end at tasks.size()), or spread it with (w * n) / workers boundaries.

12. StringsEasy

The coupon check throws NullPointerException for customers with no code. What fixes it?

if (couponCode.equals("SAVE10")) applyDiscount(cart);
  1. couponCode.equals("SAVE10") → "SAVE10".equals(couponCode)
  2. couponCode.equals("SAVE10") → couponCode == "SAVE10"
  3. couponCode.equals("SAVE10") → couponCode.equalsIgnoreCase("SAVE10")
  4. "SAVE10" → "SAVE10".intern()
Show answer

Answer: A. couponCode.equals("SAVE10") → "SAVE10".equals(couponCode)

Calling .equals on the constant is null-safe: it just returns false. Objects.equals(couponCode, "SAVE10") works too.

13. MemoryEasy

Myth or fact: Java can't have memory leaks because it has a garbage collector.

  1. Myth
  2. Fact
Show answer

Answer: A. Myth

Myth. The collector only frees objects nothing references. A static map that keeps growing, listeners that are never removed, or a cache with no eviction keep objects reachable forever: a leak.

14. CollectionsMedium

A loop removes an item from the list it’s iterating over. What happens?

List<Integer> list = new ArrayList<>(List.of(1, 2, 3));
try {
  for (Integer n : list) {
    if (n == 1) list.remove(n);
  }
  System.out.println(list);
} catch (ConcurrentModificationException e) {
  System.out.println("CME");
}

What does it output?

  1. [2, 3]
  2. CME
  3. [1, 2, 3]
  4. [1, 3]
Show answer

Answer: B. CME

The for-each loop uses an iterator, and modifying the list directly while iterating makes the iterator fail on its next step. Use iterator.remove() or list.removeIf(n -> n == 1).

15. ResourcesMedium

A few hours after deploy, every request hangs waiting for a database connection. What's the cause?

Connection c = dataSource.getConnection();
PreparedStatement s = c.prepareStatement(SQL);
ResultSet r = s.executeQuery();
return mapRows(r);
  1. The database is too slow under the new deploy's query load
  2. The connection is never closed, so the pool slowly runs out
  3. PreparedStatement can only be executed once per connection
  4. mapRows blocks the request thread while it reads rows
Show answer

Answer: B. The connection is never closed, so the pool slowly runs out

Each request borrows a connection and never returns it. Use try-with-resources (try (Connection c = ...; PreparedStatement s = ...; ResultSet r = ...)) so they close even when an exception is thrown.

Practise like this every day

InterviewGrind gives you ten questions like these each day on your iPhone, with Pro tracks for company-style loops.

Get the launch email