Enhanced For Loop - Java

  1. What does the code print?
    Answer: It prints pak, retaining first-insertion order. Whenever you see a question combining a List with a LinkedHashSet, focus on two things: deduplication and insertion order. A Set removes duplicates by definition, and LinkedHashSet specifically preserves the order in which elements were first inserted — unlike HashSet (unpredictable order) or TreeSet (sorted order). Here's what happens step by step. The list ["pear", "apple", "pear", "kiwi"] is passed into a LinkedHashSet. The second "pear" is a duplicate, so it's silently dropped. The resulting set contains {"pear", "apple", "kiwi"} in that exact first-seen order. The loop then takes charAt(0) from each: 'p', 'a', 'k'. Concatenated, result becomes "pak" — making B correct. A is wrong because it assumes the Set keeps all four elements, including the duplicate "pear". Sets never store duplicates, regardless of type. C is wrong because it describes TreeSet behavior, which sorts elements alphabetically — LinkedHashSet makes no such guarantee. D is wrong because there's no reversal logic anywhere in the code; this distractor tries to confuse you by rearranging the characters without any basis. A useful study tip: memorize the three common Set implementations as a trio — HashSet (no order), LinkedHashSet (insertion order), TreeSet (sorted order). Exam questions frequently swap these to test whether you know the behavioral difference. When you see LinkedHashSet, your mental cue should immediately be "insertion order, no duplicates."
  2. What is the result of executing this code?
    Answer: It prints 11 after processing 4 and 7. When a for-each loop encounters continue, it skips the rest of the current iteration and moves to the next element. When it encounters break, it exits the loop entirely. Keeping these two behaviors distinct is the key to tracing this code correctly. Walk through each element in order. "4" is not empty and '4' is a digit, so total becomes 4. "" is empty, so continue fires — the loop skips to the next element without adding anything. "7" is not empty and '7' is a digit, so total becomes 11. Now comes "x": it is not empty, but Character.isDigit('x') returns false, so the break fires and the loop exits immediately. "2" is never reached. The program prints 11, confirming B is correct. A is wrong because continue does not end the loop — it only skips the empty string and resumes with "7". Stopping at 4 would require a break, not a continue. C is wrong because "2" comes after "x", and the break on "x" exits the loop before "2" is ever processed. D is wrong because Integer.parseInt is never called on "x" — the !Character.isDigit(value.charAt(0)) check catches it first and triggers break, so no exception is thrown. A handy study tip: whenever you trace a loop with both continue and break, mentally label each one — "skip" vs. "stop" — before you start. That distinction prevents the most common mistakes on loop-tracing questions.
  3. What is the result of executing this code?
    Answer: It prints [2] because odd objects are removed from target. When you see Java code that iterates over one collection while modifying a different one, the key question is: which collection is being iterated, and which is being modified? Here, the for-each loop iterates over source, but all removals happen on target. Since these are two separate objects, there is no concurrent modification happening on the iterated collection. The loop visits 1, 2, and 3 in order. For odd numbers (1 and 3), target.remove(number) is called. Critically, target.remove(Integer) uses the object overload, not the index overload — so it removes the first element equal to that value, not the element at that index. After removing 1 and 3, only 2 remains, making A the correct answer. B is wrong because the loop only removes elements where number % 2 != 0, so even numbers like 2 are never removed. Believing every element is removed ignores the conditional entirely. C is wrong because source's immutability is irrelevant — you never modify source. The iteration happens safely on source, and all mutations target the mutable ArrayList called target. D is wrong because ConcurrentModificationException is thrown only when you modify the same collection you're iterating over. Since the loop iterates source and modifies target, no concurrent modification occurs. A useful rule of thumb: whenever remove(Object) is called on a List<Integer>, remember it removes by value, not by index. Confusing these two overloads is one of the most common traps in Java collection questions.
  4. What is the result of executing this code?
    Answer: It prints [a1, xy2] because the original objects are modified. When you see a question like this, ask yourself two things: does the loop body mutate the object, and does it reassign the reference? These are completely different operations in Java, and this question tests exactly that distinction. In a Java enhanced for-loop, the loop variable word holds a copy of the reference to each StringBuilder in the list. When you call word.append(word.length()), you're invoking a method on the actual object in memory — the one the list still points to. So "a" becomes "a1" (length was 1) and "xy" becomes "xy2" (length was 2). Those mutations stick because you reached through the reference to modify the underlying object. That makes C correct. The reassignment word = new StringBuilder("!") does absolutely nothing to the list. It only changes where the local variable word points — the list's internal references are untouched. This is why B is wrong: reassigning the loop variable never modifies the collection itself. A is partially right in noting the loop variable is local, but it draws the wrong conclusion. The local variable can still mutate the object it points to — it just can't change what the list holds. So the list is not unchanged. D is a clever trap suggesting append somehow reads an updated length. It doesn't — word.length() is evaluated before append runs, so it reflects the original length. The key study tip: in Java, reassigning a reference variable is not the same as modifying the object. Method calls that mutate the object (like append) will always be visible to anyone holding a reference to it.
  5. What is the result of executing this code?
    Answer: It prints {a=1, b=5} because only the even value changes. When iterating over a Map.entrySet(), you're working with live references to the actual map entries — not copies. This means calling entry.setValue() directly modifies the underlying map, which is the key concept being tested here. Trace through the loop: the first entry is "a"=1. Since 1 % 2 == 0 is false, it's skipped. The second entry is "b"=2. Since 2 % 2 == 0 is true, its value becomes 2 + 3 = 5. After the loop, the map contains {a=1, b=5}, confirming C is correct. A is wrong because it assumes entries are copied during iteration. They're not — Map.Entry objects returned by entrySet() are live views into the map. Any setValue() call is reflected immediately in the underlying map. B is wrong because it implies both entries are modified. Only "b" has an even value (2 % 2 == 0), so only that entry's value changes. "a" has an odd value and is completely untouched. D is the most tempting distractor. ConcurrentModificationException is thrown when you structurally modify a map (add or remove entries) during iteration. Calling entry.setValue() does not structurally modify the map — it simply updates an existing entry's value in place, which is explicitly permitted and safe. Study tip: Distinguish between structural modifications (adding/removing entries, which break iteration) and value updates via entry.setValue() (which are safe). This distinction frequently appears in Java exam questions involving maps and iterators.
  6. Which replacement for // LOOP causes a compilation error?
    Answer: for (Long value : values) { } When using a for-each loop in Java, the loop variable's declared type must be compatible with the element type through either assignment compatibility or autoboxing — but the key distinction is whether the conversion happens automatically at runtime. List<Integer> holds Integer objects. In a for-each loop, each element is pulled out as an Integer and assigned to the loop variable. The question is: what types can legally receive an Integer? Option D, for (Long value : values), causes the compilation error. Even though long and int are both primitives, Integer cannot be unboxed to int and then widened/narrowed to fit a Long reference — Java does not perform unboxing followed by boxing into a different wrapper type in a single step. The compiler simply cannot convert Integer to Long automatically, so this fails. Options A, B, and C all compile successfully, each for a different reason. A works because Java first unboxes Integer to int, then widens it to long — unboxing plus widening is a legal single conversion. B works because Integer is a subclass of Number, so assigning an Integer to a Number variable is straightforward upcasting. C works because every object in Java is an Object, so Integer is trivially compatible. The trap here is assuming that because Long and Integer are both number wrappers, they're interchangeable — they're not. Java won't silently convert between two different wrapper types. As a study tip, remember: Java allows one implicit conversion in assignment (widening, unboxing, or upcasting), but never two combined conversions that cross wrapper-type boundaries.
  7. What is the result of executing this code?
    Answer: It prints 11:[2, 3, 4]. When you see a for-each loop modifying a primitive variable like int n, ask yourself: am I changing the list, or just a local copy? That's the core concept being tested here. In a for-each loop, Java copies each element's value into the loop variable n. When you write n++, you're incrementing that local copy — the original ArrayList is never touched. So nums remains [2, 3, 4] throughout. This immediately rules out C and D, which both show a modified list. Now trace the total calculation. For n = 2: it's even, so n becomes 3, and total += 3 → total is 3. For n = 3: it's odd, so no change, and total += 3 → total is 6. For n = 4: it's even, so n becomes 5, and total += 5 → total is 11. The output is 11:[2, 3, 4], confirming B is correct. A is wrong because it uses 9 as the total, which would be the result of adding the original values 2 + 3 + 4 without applying the increment logic to n at all. C and D both incorrectly show the list as [3, 3, 5], as if n++ mutated the ArrayList's contents — it doesn't. D compounds that mistake by also using the wrong total of 9. A good rule of thumb: in a for-each loop, modifying a primitive loop variable never affects the underlying collection. If you need to modify the list, use a traditional index-based for loop with nums.set(i, value).
  8. What happens when this code is executed?
    Answer: It throws ConcurrentModificationException before the final print. Whenever you see a for-each loop modifying the collection it's iterating over, your first thought should be: this is going to throw a ConcurrentModificationException. Here's why. Java's enhanced for-each loop works by internally using an Iterator. When the loop begins, the iterator captures a "modification count" (called modCount) from the ArrayList. Every structural change to the list — including remove() — increments that count. On each iteration, the iterator checks whether its saved count still matches the list's current count. The moment they differ, it throws a ConcurrentModificationException. In this code, removing "a" during the first iteration triggers exactly that check on the next iteration, crashing the program before the System.out.print line is ever reached. A is wrong because it assumes removal inside a for-each loop is safe — it isn't. The list is structurally modified while the iterator is active, which violates the iterator's contract. B is a nonsense distractor; removing an item from the list absolutely affects the list itself, not just the local loop variable item. C would apply if you tried to remove from an unmodifiable list (like one returned directly by List.of()), but here you're using new ArrayList<>(...), which is fully mutable — so UnsupportedOperationException doesn't apply. Study tip: Whenever you need to remove elements while iterating, use iterator.remove() explicitly, or use removeIf() — both are designed to handle structural modification safely. Memorize this rule: *never call the collection's own remove() inside a for-each loop.*
  9. What happens when this code is executed?
    Answer: It throws NullPointerException before the final print. Whenever you see a question mixing primitive types with nullable collections, your first instinct should be to look for autoboxing/unboxing — because that's where NullPointerException hides. Here, the list contains Integer objects (a reference type), but the enhanced for-loop declares int score (a primitive). Each iteration, Java automatically unboxes the Integer into an int. When the loop reaches null, Java attempts to call .intValue() on a null reference — and that's an instant NullPointerException. This crash happens before total is ever printed, which is why C is correct. A is tempting because "null is skipped" sounds logical — but nothing in this code skips null. The if (score == 0) check never runs because the unboxing already fails before the condition is evaluated. Null is not zero. B is wrong on two counts: null doesn't terminate an enhanced for-loop, and a NullPointerException is thrown rather than any graceful exit. D is incorrect because the code does compile. Java allows a primitive loop variable over a List<Integer> because the compiler knows unboxing will handle the conversion at runtime. The error is a runtime problem, not a compile-time one. Study tip: Any time you unbox a wrapper type (Integer, Double, Boolean, etc.) — whether through assignment, arithmetic, or a primitive for-loop variable — ask yourself: could this reference be null? If yes, expect a NullPointerException at that exact point, not later.
  10. What does the code print?
    Answer: It prints a1 . When you see nested loops with a break statement, your job is to carefully track which loop the break exits — in Java, break only exits the innermost loop it's in. Let's trace through the code. The outer loop iterates over labels = ["ab", "c"] and the inner loop iterates over numbers = [1, 2, 3]. **First outer iteration: label = "ab" (length 2)** - number = 1: label.length() (2) == 1? No. Append "a1 " → result = "a1 " - number = 2: label.length() (2) == 2? Yes → **break** exits the inner loop immediately. **Second outer iteration: label = "c" (length 1)** - number = 1: label.length() (1) == 1? Yes → **break** exits the inner loop immediately. Nothing is appended. The outer loop then ends. Final result: "a1 ", so A is correct. B (a1 c2 c3) would only be correct if break skipped the first number but continued with the rest — that's not how break works; it exits the loop entirely. C (a1 a3) incorrectly assumes the break skips just number = 2 and resumes at number = 3, which would be continue behavior, not break. D (a1 c1) misreads the condition — for "c", number = 1 triggers the break before appending, so nothing is added. A great study tip: always ask yourself, "Does break appear inside a nested loop?" If yes, it only exits one level — the innermost one. Confusing break with continue or assuming it exits all loops is one of the most common Java traps.

Start this quiz