| for-each loop | Works on arrays and Iterable; no index access; read-only iteration |
| switch (Java 14+) | Arrow syntax, no fall-through, can return value |
| break vs continue | break exits loop; continue skips to next iteration |
| do-while | Executes body at least once before checking condition |
| Labeled break | break outerLabel; — exits to labeled outer loop |
| Iterator.remove() | Only safe way to remove during iteration |
| switch types | byte,short,int,char,String,enum,Integer,Byte,Short,Character |
| infinite loop | for(;;){} or while(true){} — needs break/return to exit |
Java Control Flow Interview Questions & Answers
Q1. What are the types of control flow statements in Java?
A: Java has three categories: selection (if, if-else, switch), iteration/loops (for, for-each, while, do-while), and jump (break, continue, return, throw). These control the order in which statements execute based on runtime conditions.
Q2. What is the difference between if-else and switch statements?
A: if-else works with any boolean expression and supports ranges. switch compares equality against a fixed set of constants (byte, short, int, char, String, enum). switch is faster for many equality checks (compiler can use jump table). switch cannot test ranges or null (though switch patterns in Java 21+ add more power).
Q3. What types can be used in a switch statement?
A: Traditional switch: byte, short, int, char, String (Java 7+), enum, and their wrappers Byte, Short, Integer, Character. Cannot use long, float, double, boolean, or any other Object (before Java 21 patterns). Java 21 pattern matching switch allows any type.
Q4. What is fall-through in a switch statement?
A: In traditional switch, if a case has no break, execution "falls through" to the next case. This can be intentional (share code between cases) or a bug. Java 14+ switch expressions with arrow syntax (->) never fall through.
// Fall-through example
switch (day) {
case "MON": case "TUE": case "WED": case "THU": case "FRI":
System.out.println("Weekday");
break;
case "SAT": case "SUN":
System.out.println("Weekend");
break;
}
// Modern switch expression (Java 14+) — no fall-through
String type = switch (day) {
case "MON", "TUE", "WED", "THU", "FRI" -> "Weekday";
case "SAT", "SUN" -> "Weekend";
default -> "Unknown";
};
Q5. What is the difference between for loop and for-each loop?
| Feature | for loop | for-each loop |
|---|---|---|
| Index access | Yes | No |
| Element removal | Possible (with care) | ConcurrentModificationException |
| Works with | Arrays, any indexed structure | Arrays & Iterable implementations |
| Readability | More verbose | Cleaner for simple iteration |
Q6. What is the difference between while and do-while loops?
A: while: checks condition BEFORE executing body — body may never run if condition is false initially. do-while: executes body FIRST, then checks condition — body always runs at least once. Use do-while for "execute at least once" logic like input validation prompts.
// while — may skip body
while (hasMore()) { process(); }
// do-while — guaranteed at least one run
do {
input = scanner.nextLine();
} while (input.isEmpty());
Q7. What does break do inside a nested loop?
A: break exits the innermost enclosing loop (or switch) only. To break out of multiple levels of nesting, use a labeled break: define a label before the outer loop and break labelName; from anywhere inside.
outer:
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (i + j == 6) break outer; // exits both loops
System.out.println(i + ", " + j);
}
}
Q8. What is the difference between break and continue?
A: break: immediately exits the loop, no more iterations. continue: skips the rest of the current iteration and goes to the next. Both work with labels for nested loops. return: exits the entire method.
Q9. What causes ConcurrentModificationException and how do you avoid it?
A: Modifying a collection while iterating with for-each (which uses Iterator internally) throws ConcurrentModificationException. Solutions: use Iterator.remove(), use removeIf() (Java 8+), collect elements to remove then remove after loop, or use concurrent collections (CopyOnWriteArrayList).
List<String> list = new ArrayList<>(Arrays.asList("a","b","c"));
// WRONG — ConcurrentModificationException
for (String s : list) { if ("b".equals(s)) list.remove(s); }
// CORRECT — Iterator approach
Iterator<String> it = list.iterator();
while (it.hasNext()) { if ("b".equals(it.next())) it.remove(); }
// CORRECT — Java 8+ removeIf
list.removeIf(s -> "b".equals(s));
Q10. What is the Iterator pattern in Java?
A: Iterator provides sequential access to collection elements without exposing the underlying structure. The Iterable interface has iterator(). The Iterator interface has hasNext(), next(), and optional remove(). For-each loops internally use Iterator.
Q11. What is the difference between Iterator and ListIterator?
A: Iterator: forward-only, works on any Collection, has hasNext/next/remove. ListIterator: bidirectional (hasPrevious/previous), only for List, can add/set/remove elements, provides current index. Use ListIterator when you need to traverse backwards or modify elements in place.
Q12. Can you modify a list while using an enhanced for-each loop?
A: You cannot add or remove from the list (ConcurrentModificationException). You CAN modify the current element's state if it's a mutable object — since you have the reference and are not modifying the list's structure. For structural modification, use Iterator.remove() or removeIf().
Q13. What is a labeled continue statement?
A: A labeled continue skips the rest of the current iteration in the labeled (outer) loop: continue outerLabel; skips to the next iteration of the outer loop. Rarely needed — complex control flow often indicates a need for refactoring into helper methods.
Q14. What is the ternary operator and when should you use it?
A: condition ? valueIfTrue : valueIfFalse. Use for simple, readable conditional expressions (e.g., String role = isAdmin ? "Admin" : "User"). Avoid for complex conditions, multiple nesting, or when either branch has side effects — switch to if-else for clarity.
Q15. What are the parts of a standard for loop?
A: for (init; condition; update) { body }. All three parts are optional: for(;;) is infinite loop. Init: runs once before loop starts. Condition: checked before each iteration; false exits loop. Update: runs after each iteration body. Multiple init/update expressions separated by comma.
Q16. What is an infinite loop and when is it valid?
A: while(true){} or for(;;){} are infinite loops. Valid uses: event loops, server main loops (while waiting for requests), background daemon threads, state machines. Always include a break/return condition or handle termination via thread interruption.
Q17. What is the difference between Iterable and Iterator?
A: Iterable is a contract that an object can be iterated — it provides iterator(). Iterator is the cursor used to traverse elements, maintaining state (current position). Iterable is the factory; Iterator is the stateful traverser. For-each calls iterable.iterator() once and then loops via hasNext/next.
Q18. Can a switch statement fall through to default?
A: Yes — default can appear anywhere in switch (not just last). If no case matches and fall-through reaches default (or default is reached directly), default executes. If default has no break and is not last, execution falls through to subsequent cases after it.
Q19. What is the switch expression (Java 14+)?
A: Switch expressions return a value and use arrow (->) syntax without fall-through. Multiple labels: case 1, 2, 3 -> "few". Blocks with yield for multi-statement cases. The compiler enforces exhaustiveness (all cases covered, else needs default).
int numDays = switch (month) {
case JANUARY, MARCH, MAY, JULY, AUGUST, OCTOBER, DECEMBER -> 31;
case APRIL, JUNE, SEPTEMBER, NOVEMBER -> 30;
case FEBRUARY -> {
if (year % 4 == 0) yield 29;
else yield 28;
}
};
Q20. What happens if you omit the default case in a switch?
A: For switch statements: nothing happens if no case matches (execution continues after switch). For switch expressions: the compiler may warn/error about non-exhaustive switches. With enum: if all enum values are covered, no default needed. Always add default in switch statements for safety.
Q21. How do you iterate over a Map in Java?
A: Several ways: map.entrySet() for-each (most common, access both key and value), map.keySet() for-each (keys only), map.values() for-each (values only), map.forEach((k,v) -> ...) (Java 8+), or Iterator on entrySet. Avoid iterating keySet and calling get(key) inside — use entrySet for O(1) access.
Map<String, Integer> map = Map.of("a", 1, "b", 2);
// Best practice — entrySet
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
// Java 8+ forEach
map.forEach((k, v) -> System.out.println(k + "=" + v));
Q22. What is the difference between for-each and stream forEach()?
A: for-each is a language construct, translates to Iterator. Stream forEach() is a terminal operation on a Stream — enables lazy evaluation, parallel processing, and chaining with other stream operations. Use Stream when you need filtering/mapping; use for-each for straightforward iteration.
Q23. What is a fail-fast iterator?
A: Fail-fast iterators (e.g., ArrayList, HashMap iterators) throw ConcurrentModificationException if the collection is structurally modified during iteration (except through iterator's own remove()). They use a modCount check. Fail-safe iterators (CopyOnWriteArrayList, ConcurrentHashMap) work on a copy and don't throw.
Q24. What is the difference between Enumeration and Iterator?
A: Enumeration (legacy, JDK 1.0): hasMoreElements()/nextElement(), no remove method, used with Vector/Hashtable. Iterator (JDK 1.2+): hasNext()/next()/remove(), more modern, consistent with Collection framework. Prefer Iterator or for-each. Enumeration exists for legacy code compatibility.
Q25. What is the ListIterator and when do you use it?
A: ListIterator allows bidirectional traversal, element modification (set()), and element insertion (add()) during iteration. Only available for List implementations. Use when you need to traverse backward, replace elements in-place, or add elements during traversal.
Q26. Can you use String in switch before Java 7?
A: No — String in switch was introduced in Java 7. Before Java 7, only integral types (byte, short, int, char) and enum were allowed. The switch on String works by calling hashCode() and then equals() internally — it's compiled to efficient bytecode.
Q27. What is the difference between return in void and non-void methods?
A: In non-void methods, return value; must return a value of the declared type. In void methods, bare return; is optional (exits method immediately). Every non-void method must have a return statement on every execution path (compile error otherwise).
Q28. What happens when you call break inside a switch inside a for loop?
A: break breaks out of the innermost enclosing switch or loop. If switch is inside a for loop, break exits the switch — the for loop continues. To exit the for loop, use a labeled break or set a boolean flag.
loop:
for (int i = 0; i < 10; i++) {
switch (i % 3) {
case 0: System.out.println("zero"); break; // exits switch
case 1: System.out.println("one"); break loop; // exits for loop
}
}
Q29. What is the for-each loop's limitation with arrays?
A: For-each on arrays gives read-only element access — you cannot modify the array element through the loop variable for primitives (modifying the variable doesn't affect the array). For objects, you can call mutating methods on the object. To modify array elements, use a traditional for loop with index.
Q30. What is the difference between while(true) and for(;;)?
A: Both are semantically infinite loops. for(;;) is slightly more idiomatic in some styles, while(true) is more readable. Both compile to identical bytecode (JVM optimizer treats them equivalently). Choose based on team coding standards.
Q31. What is pattern matching in switch (Java 21)?
A: Java 21 switch can match patterns including type patterns (case Integer i), guarded patterns (case Integer i when i > 0), and null handling. This eliminates verbose instanceof chains.
Object obj = "hello";
String result = switch (obj) {
case Integer i -> "int: " + i;
case String s when s.length() > 3 -> "long string: " + s;
case String s -> "short string: " + s;
case null -> "null";
default -> "other";
};
Q32. What does yield do in switch expressions?
A: yield value; is used inside a block case of a switch expression to return a value. Like return for switch expressions. Only valid in switch expression contexts. Arrow cases (->) don't need yield for single expressions; yield is needed for multi-statement blocks.
Q33. How does the Iterable interface work with for-each?
A: Any class implementing Iterable<T> can be used in for-each. The compiler translates for (T item : collection) to: Iterator<T> it = collection.iterator(); while(it.hasNext()) { T item = it.next(); ... }. Implement Iterable to make custom data structures work with for-each.
Q34. What is a range-based condition and how to express it in Java?
A: Java switch cannot express ranges directly (unlike C# or Kotlin). Use if-else for ranges. Java 21 pattern matching switch with when guards can express ranges: case Integer i when i >= 0 && i < 100 -> "low". Traditional approach: if (x >= 0 && x < 100) { ... }.
Q35. What is the difference between break with and without label?
A: Unlabeled break: exits the innermost loop or switch. Labeled break label: exits the loop or switch marked with that label. Labels are identifiers followed by colon placed before a loop statement. Use labeled breaks sparingly — they often indicate code that should be extracted into a method.
Q36. How do you iterate in reverse over a List?
A: Options: traditional for loop from size()-1 to 0; ListIterator.hasPrevious()/previous(); Java 8 stream with Comparator reversal. For arrays: same reversed for loop. Collections.reverse() modifies the list in place (destructive).
List<String> list = Arrays.asList("a","b","c");
// Reverse loop
for (int i = list.size()-1; i >= 0; i--) System.out.println(list.get(i));
// ListIterator
ListIterator<String> it = list.listIterator(list.size());
while (it.hasPrevious()) System.out.println(it.previous());
Q37. What is the difference between if-else if chain and switch?
A: if-else: evaluates each condition in order — O(n) in worst case. switch: can use jump table for integral types — O(1) for many compilers. switch is cleaner for many equality checks against a single variable. if-else supports complex boolean expressions; switch only equality.
Q38. Can you use null in a switch case?
A: Traditional switch: passing null throws NullPointerException. Java 21 switch patterns: case null -> is valid. Always null-check before traditional switch. For switch expressions in Java 21+, you can explicitly handle null with a case.
Q39. What is the difference between for(int i: arr) and for(int i = 0; i < arr.length; i++)?
A: for-each: no index, read-only to array elements (for primitives), cleaner. Traditional for: index available, can write to array elements, can iterate in any order/step, can skip elements. For array element modification, use traditional for. For parallel streams or concurrent processing, use indices.
Q40. How does the compiler handle switch on String?
A: Compiler generates code that: (1) calls hashCode() on the input string, (2) uses switch on the hash code, (3) calls equals() within each case to confirm (handles hash collisions). Result: efficient O(1) dispatch while maintaining correctness.
Q41. What is an early return and why is it considered good practice?
A: Early return exits a method as soon as a condition is met, avoiding deep nesting. Guard clauses at the top of a method handle edge cases first: if (input == null) return empty;. Reduces indentation levels and makes the "happy path" clearer. Preferred over deeply nested if-else chains.
Q42. What is the difference between continue and break in a while loop?
A: In while(condition): continue re-evaluates the condition immediately. break exits the while loop entirely. In do-while: continue re-evaluates the trailing condition. Both work with labels for nested loops.
Q43. What is the Spliterator interface?
A: Spliterator (Java 8+) is like an Iterator but designed for parallel processing. It can split itself (trySplit()) into two Spliterators for parallel streams. Provides tryAdvance() (process one element), forEachRemaining(), and characteristics (ORDERED, DISTINCT, SORTED, etc.).
Q44. How does Stream.forEach() differ from Iterable.forEach()?
A: Iterable.forEach(Consumer): iterates over the collection once. Stream.forEach(Consumer): is a terminal stream operation that can be parallelized. Stream operations can be lazy; Iterable.forEach is eager. For parallel execution, use parallelStream().forEach() but beware of order guarantees.
Q45. What is the difference between for-each and traditional for loop performance?
A: For ArrayList: traditional for loop is slightly faster (direct index access vs iterator overhead). For LinkedList: for-each is faster (traverses nodes sequentially; traditional for loop with get(i) is O(n²)). For arrays: similar performance, JIT optimizes both well. Prefer for-each for readability unless index is needed.
Q46. What happens if you modify a loop variable inside the loop body?
A: For a traditional for loop: modifying the loop variable inside the body affects the loop — the update expression still applies after each iteration. Common bug: for (int i = 0; i < 10; i++) { i++; } — loop only runs 5 times. For for-each: the loop variable is a copy — modifying it doesn't affect the array/collection.
Q47. What is a for-each loop compiled to for an array?
A: For arrays, for-each compiles to a length-cached traditional for loop — NOT an Iterator. Example: for (int x : arr) → for (int i = 0; i < arr.length; i++) { int x = arr[i]; }. So for arrays, for-each is as fast as traditional for.
Q48. What is the best way to remove elements from a List while iterating?
A: Three safe approaches: (1) Iterator.remove() — works with all collections; (2) List.removeIf(predicate) — cleanest for filter removal; (3) collect items to remove in another list, then call list.removeAll(toRemove). Never remove by index while iterating forward (indices shift).
Q49. What is the difference between break inside try-catch and break inside switch?
A: break inside a switch exits the switch. break inside a try block inside a loop exits the loop. break inside a catch exits the loop. In all cases, finally block still runs before control transfers. break does NOT bypass finally.
Q50. What are the three parts of a for loop and can any be empty?
A: Init, condition, update — all are optional. for (;;) is valid (infinite loop). for (int i = 0;;i++) has no condition (infinite). for (;i < 10;) has no init or update (manual update in body). Multiple expressions separated by comma in init and update parts.
Q51. What is a sentinel-controlled loop vs a counter-controlled loop?
A: Counter-controlled: iterates a fixed number of times (for (int i = 0; i < n; i++)). Sentinel-controlled: iterates until a special value (sentinel) is encountered (while ((line = reader.readLine()) != null)). Sentinel loops are useful when count is unknown — reading file lines, parsing streams.
Q52. What is the difference between logical && and | | short-circuit behavior in loops?
A: In loop conditions, short-circuit prevents index-out-of-bounds or null pointer: while (i < arr.length && arr[i] != null) — the null check only runs if index is valid. Using & instead would evaluate both sides, potentially throwing ArrayIndexOutOfBoundsException.
Q53. What is the difference between Iterable and Collection?
A: Iterable is a top-level interface with just iterator(). Collection extends Iterable and adds size(), isEmpty(), contains(), add(), remove(), etc. All Collection implementations are Iterable. Arrays implement Iterable (via Arrays.asList() wrapper). Your custom data structures can implement Iterable directly.
Q54. How do you loop over a stream with an index?
A: Streams don't provide index natively. Options: use traditional for loop; use IntStream.range(0, list.size()).forEach(i -> process(list.get(i), i)); or use Streams.zip() from Guava. IntStream.range is clean and efficient.
List<String> list = List.of("a","b","c");
IntStream.range(0, list.size())
.forEach(i -> System.out.println(i + ": " + list.get(i)));
Q55. What is a while vs do-while performance difference?
A: No significant performance difference — JIT optimizes both equivalently. The semantic difference (guaranteed first execution) is what matters. Choose based on logic requirements: if the loop body must always run at least once, use do-while. Otherwise while is clearer and more common.
Q56. What happens when an exception is thrown inside a loop?
A: The loop is terminated (unless the exception is caught inside the loop body). If caught inside: the loop continues normally. If not caught inside: the method's exception propagates up, unwinding the loop. Always handle exceptions appropriately and decide whether to continue looping or abort.
Q57. How does Stream.iterate() differ from a while loop?
A: Stream.iterate(seed, hasNext, next) creates a lazily-evaluated stream of values. Unlike while loops, it supports parallel processing, stream operations (filter, map), and can be composed with other streams. It does NOT have mutable loop variable — each step produces new value functionally.
// Generate Fibonacci with Stream.iterate
Stream.iterate(new long[]{0,1}, f -> new long[]{f[1], f[0]+f[1]})
.limit(10)
.map(f -> f[0])
.forEach(System.out::println);
Q58. What is the difference between for-each on a Set vs List?
A: For List: iteration order is guaranteed (insertion order for ArrayList/LinkedList). For HashSet: iteration order is undefined (depends on hash codes). For LinkedHashSet: insertion order maintained. For TreeSet: sorted order. The for-each construct works the same; the order depends on the collection type.
Q59. What is an enhanced switch statement vs switch expression?
A: Switch statement (both traditional and enhanced with arrow) is an imperative statement — it performs actions. Switch expression (Java 14+) produces a value that can be assigned. Switch expressions must be exhaustive (cover all cases). Switch statements can be non-exhaustive (then nothing happens on no match).
Q60. What are common mistakes in for loops?
A: Off-by-one errors (i <= arr.length instead of i < arr.length), accidentally modifying loop variable in body, comparing wrong loop bound (e.g., size() vs length), infinite loops from missing increment, and iterating over collection while modifying it. Always test boundary conditions.
Q61. What is the difference between Arrays.asList() and List.of() for iteration?
A: Arrays.asList(): fixed-size list backed by array, allows set() but not add()/remove(). List.of() (Java 9+): fully immutable, no add/remove/set — throws UnsupportedOperationException. For-each iteration works the same on both. For modification, use new ArrayList<>(Arrays.asList(...)).
Q62. What is tail recursion and does Java optimize it?
A: Tail recursion: the recursive call is the last operation in the method (nothing left to compute after it). Java's JVM does NOT perform tail-call optimization — each recursive call adds a stack frame. Deep tail recursion still causes StackOverflowError. Manually convert to iteration with an explicit stack or use trampoline pattern.
Q63. How do you implement a custom Iterable class?
A: Implement Iterable<T> and return an Iterator<T> from iterator(). The Iterator needs hasNext() and next() (and optionally remove()). This enables for-each on your class.
class Range implements Iterable<Integer> {
private final int start, end;
Range(int start, int end) { this.start = start; this.end = end; }
public Iterator<Integer> iterator() {
return new Iterator<>() {
int current = start;
public boolean hasNext() { return current < end; }
public Integer next() { return current++; }
};
}
}
for (int n : new Range(1, 5)) System.out.println(n); // 1 2 3 4
Q64. What is a guard clause?
A: A guard clause is an early return at the top of a method to handle invalid/edge cases before the main logic. Keeps the main path unindented and readable. Example: if (list == null || list.isEmpty()) return Collections.emptyList(); at the top of a method that processes the list.
Q65. How does Java's switch compare to other languages?
A: Unlike C/C++ (integer-only, mandatory fall-through), Java's switch supports String and enum. Unlike Kotlin (expression by default, sealed class support), Java required language evolution through Java 14+ for switch expressions. Python has no switch (uses dict dispatch); Go added generic switch in recent versions. Java 21's pattern matching switch is now among the most powerful.
Q66. What is the difference between sequential and parallel streams?
A: Sequential stream (default): processes elements in order on calling thread. Parallel stream (parallelStream() or .parallel()): uses ForkJoinPool, processes elements concurrently — faster for CPU-intensive, large datasets. Parallel streams have overhead — only beneficial for large datasets. Order not guaranteed; use forEachOrdered() if needed.
Q67. What is Stream.takeWhile() and dropWhile() (Java 9+)?
A: takeWhile(predicate): returns elements from the beginning while predicate is true, stops at first false (useful for sorted streams). dropWhile(predicate): drops elements while predicate is true, returns from first false element onward. Both are short-circuiting operations.
Q68. What is the difference between while loop and recursion?
A: Loops use iteration on the heap (no extra stack frames). Recursion uses the call stack (each call adds a frame — risk of StackOverflowError for deep recursion). Recursion is often cleaner for tree/graph problems. Java does not optimize tail recursion. For deep recursion, convert to iterative with an explicit stack.
Q69. What is the Collections.unmodifiableList() iteration behavior?
A: Iteration (for-each, iterator) works normally on unmodifiableList. Calling remove() on the iterator throws UnsupportedOperationException. Calling add()/remove() on the list throws UnsupportedOperationException. It's a read-only view of the underlying list — mutations to the original list are reflected.
Q70. What is the difference between Stream.peek() and forEach()?
A: peek(Consumer) is an intermediate operation — it passes elements through while performing a side effect, and is lazy (only executes when a terminal operation is called). forEach(Consumer) is a terminal operation — consumes the stream. Use peek for debugging; use forEach for final processing.
Q71. What happens when you call iterator.next() when hasNext() is false?
A: Throws NoSuchElementException. Always check hasNext() before calling next(). This is why for-each is safer — the compiler generates the hasNext() check. Always validate before advancing an iterator in manual iteration code.
Q72. What is a for-each index workaround in Java?
A: Use an AtomicInteger or int[] wrapper since lambda requires effectively final variables: AtomicInteger index = new AtomicInteger(); list.forEach(e -> process(e, index.getAndIncrement()));. Or simply use IntStream.range() which is cleaner and more readable.
Q73. What is the difference between break in a switch inside a method and in a loop?
A: break always exits the nearest enclosing switch or loop. Inside a switch that's inside a method (no loop): break exits the switch, then method execution continues. Inside a switch inside a loop: break exits the switch (loop continues). To exit the loop from inside a switch, use labeled break or a flag variable.
Q74. What is the difference between CopyOnWriteArrayList and ArrayList in iteration?
A: ArrayList iterator: fail-fast (ConcurrentModificationException if modified during iteration). CopyOnWriteArrayList iterator: fail-safe (works on a snapshot of the array at iterator creation time). Mutations to the list after iterator creation are not reflected. Best for read-heavy, write-rare scenarios.
Q75. How do you iterate over a 2D array?
A: Nested for loops (most common), nested for-each, or stream: Arrays.stream(matrix).flatMapToInt(Arrays::stream).sum(). For-each on a 2D array: outer loop iterates over rows (each row is an int[]), inner loop iterates over columns (elements).
int[][] matrix = {{1,2,3},{4,5,6},{7,8,9}};
for (int[] row : matrix) {
for (int val : row) System.out.print(val + " ");
System.out.println();
}
Q76. What is the difference between Collections.synchronizedList() iteration and normal iteration?
A: synchronizedList wraps each individual method call with synchronized. BUT iteration is NOT automatically thread-safe — you must manually synchronize the entire iteration: synchronized(list) { for (String s : list) { ... } }. Failing to do this can cause ConcurrentModificationException in multi-threaded scenarios.
Q77. What is the difference between for-each and Iterator for Map?
A: Map doesn't implement Iterable directly. You must iterate over entrySet(), keySet(), or values() (all return collections/sets). For-each on entrySet() gives both key and value efficiently. Map.forEach(BiConsumer) (Java 8+) is cleanest. Never iterate keySet() and call map.get() inside — use entrySet().
Q78. What is the purpose of the do-while loop idiom for retrying?
A: do-while is perfect for retry logic — attempt first, then check if retry needed: do { result = tryOperation(); } while (!result.isSuccess() && retries++ < maxRetries);. Or for menu systems: display menu, get input, process — repeat until exit chosen.
Q79. What is the difference between Stream.limit() and break in a loop?
A: Stream.limit(n) limits the stream to n elements — lazy and short-circuits with infinite streams. Like break in a for loop but composable with other stream operations. Use limit() for taking first n elements from a stream/generator. Cannot use break inside stream operations.
Q80. What is the Iterator.remove() method and when is it needed?
A: Iterator.remove() removes the last element returned by next() from the underlying collection safely during iteration. It's the ONLY safe way to remove elements while iterating with an Iterator. Must call next() before each remove(). Not all iterators support remove() — throws UnsupportedOperationException if not supported.
Q81. How does for-each handle null collections?
A: If the Iterable in for-each is null, a NullPointerException is thrown when Java calls .iterator() on it. Always null-check collections before for-each: if (list != null) for (String s : list). Or use null-safe utilities: for (String s : Optional.ofNullable(list).orElse(Collections.emptyList())).
Q82. What is Stream.generate() vs Stream.iterate()?
A: Stream.generate(Supplier): generates an infinite stream from a supplier (each call to supplier produces the next element). No seed or step. Stream.iterate(seed, UnaryOperator): each element is derived from the previous (stateful). Use generate for random values; iterate for sequences.
Q83. What is the difference between traditional for loop and iterator in terms of ConcurrentModificationException?
A: Traditional for loop with index: does NOT use Iterator internally — no ConcurrentModificationException when removing by index (but be careful with index shifting). Iterator/for-each: does trigger CME on structural modification. Rule: use index-based removal only when you understand the index-shifting implications.
Q84. What is the Deque iteration pattern?
A: Deque can be iterated head-to-tail (Deque.iterator()) or tail-to-head (Deque.descendingIterator()). Common pattern for stack-like processing: while (!deque.isEmpty()) { process(deque.poll()); }. For-each iterates head-to-tail by default.
Q85. What is the difference between while(iterator.hasNext()) and for-each?
A: Functionally equivalent — for-each is syntactic sugar for the while(iterator.hasNext()) pattern. The difference: for-each scope-limits the iterator (you can't access it after the loop). While gives you access to the iterator for manual remove(). Use for-each for readability; manual iterator when you need remove().
Q86. What are the types of control flow in Java programs?
A: Normal: sequential execution top-to-bottom. Branch: if/switch changes path. Loop: for/while/do-while repeats. Exception: try/catch/finally, throw. Method call: invokes another method. Thread: concurrent execution paths. Understanding all types helps in debugging execution order and stack traces.
Q87. How do you exit a nested for-each loop?
A: Options: (1) Labeled break (labeled must be on a for loop, not for-each variable); (2) Set a boolean flag and break on it; (3) Extract into a method and use return; (4) Use an AtomicBoolean flag. Extracting into a method is the cleanest: return from the method when the condition is met.
Q88. What is the difference between Stream.forEachOrdered() and Stream.forEach()?
A: forEach(): in parallel streams, does not guarantee encounter order (faster). forEachOrdered(): guarantees encounter order even in parallel streams (slower, but predictable). For sequential streams, both produce the same order. Use forEachOrdered when order matters for side effects.
Q89. What is the difference between loop unrolling and normal loops?
A: Loop unrolling is a JIT compiler optimization: if a loop runs a small known number of iterations, the JIT may inline the body multiple times to reduce loop overhead (branch prediction, counter checks). You don't control this in Java — the JIT decides based on profiling. Understanding it helps explain why tight loops are fast in Java.
Q90. What are the performance implications of using a traditional for loop on a LinkedList?
A: Calling list.get(i) on a LinkedList is O(n) — must traverse from the start each time. A for loop with index gives O(n²) overall. Always use for-each (or iterator) with LinkedList — it maintains a pointer and advances sequentially: O(n) total.
Q91. How do you iterate over a PriorityQueue?
A: PriorityQueue iterator does NOT traverse in priority order. To drain in priority order: while (!pq.isEmpty()) { process(pq.poll()); }. The for-each loop iterates internal array order (undefined). Use poll() to consume elements in correct priority order.
Q92. What is the yield keyword in switch expressions (Java 13+)?
A: yield value; in a switch expression block case returns a value from that case — like return for the switch expression. In arrow cases (->), yield is implicit for single expressions. yield is a context keyword (only special inside switch expressions), not a reserved keyword everywhere.
Q93. What is the difference between Iterator and Enumeration in terms of thread safety?
A: Enumeration (on Vector/Hashtable): the collection is synchronized, but the enumeration itself is not thread-safe. Iterator (on synchronized collections): same situation — synchronize on the collection during full iteration. CopyOnWriteArrayList/ConcurrentHashMap iterators: truly thread-safe — work on snapshots.
Q94. What is the purpose of Stream.findFirst() vs Stream.findAny()?
A: findFirst(): returns the first element (respects encounter order). findAny(): returns any element (faster in parallel streams as no ordering constraint). Both return Optional. For sequential streams, both typically return the same element. Prefer findAny() for parallel streams when order doesn't matter.
Q95. How do you safely iterate over a ConcurrentHashMap?
A: ConcurrentHashMap iterator is weakly consistent — reflects state at or since creation, doesn't throw ConcurrentModificationException. Suitable for non-atomic compound operations. For atomic operations, use CHM's own compute/merge/putIfAbsent methods. forEach(parallelismThreshold, action) for parallel processing.
Q96. What is the difference between Arrays.stream() and Stream.of() for arrays?
A: For primitive arrays: Arrays.stream(int[]) returns IntStream (primitive stream, no boxing). Stream.of(int[]) returns Stream<int[]> (stream of one array element — a common mistake). For object arrays, both work: Arrays.stream(String[]) = Stream.of(String[]).
Q97. How does the enhanced for loop work with a custom data structure?
A: Implement Iterable<T> on your class and provide an Iterator<T> from iterator(). The Iterator must implement hasNext() and next(). Once done, your class works seamlessly with for-each, Collection utilities, and streams (via StreamSupport.stream(spliterator(), false)).
Q98. What is the difference between switch case with String vs enum?
A: Enum switch: type-safe, no null risk (enums can't be null), compiler warns on missing cases. String switch: runtime hashCode+equals comparison, null throws NPE. Prefer enum switch when the set of values is fixed and known at compile time — it's more robust and readable.
Q99. What is a recursive vs iterative approach for traversing a binary tree?
A: Recursive: clean code, natural for tree structure, but risks StackOverflow for very deep trees. Iterative: uses an explicit Stack (or Deque), no stack overflow risk, more complex code. For interview problems, start with recursive (easier to code), then optimize to iterative if required.
// Iterative inorder traversal
void inorder(TreeNode root) {
Deque<TreeNode> stack = new ArrayDeque<>();
TreeNode curr = root;
while (curr != null || !stack.isEmpty()) {
while (curr != null) { stack.push(curr); curr = curr.left; }
curr = stack.pop();
System.out.println(curr.val);
curr = curr.right;
}
}
Q100. What are the best practices for writing loops in Java?
A: Cache collection size outside loop (int size = list.size()). Use for-each for readability. Use Iterator.remove() for safe removal. Avoid modifying collections during iteration. Prefer Stream API for functional operations. Limit loop body complexity (extract into methods). Always test boundary conditions (0, 1, n-1, n).
Q101. What is Stream.anyMatch() vs Stream.allMatch() vs Stream.noneMatch()?
A: anyMatch(pred): true if any element matches (short-circuits on first match). allMatch(pred): true if all elements match (short-circuits on first non-match). noneMatch(pred): true if no elements match (short-circuits on first match). All return Optional-free booleans — false for empty streams except allMatch (returns true for empty).
Q102. What is the difference between for loop with i < n and i != n?
A: i < n: safe even if i somehow jumps past n (won't infinite loop). i != n: can infinite loop if i is incremented by more than 1 and jumps over n. Always use < for numeric bounds unless you have specific reason for !=. This matters for loop step sizes other than 1.
Post a Comment
Add