Bird
Raised Fist0

Iterator Pattern - Traversal Without Exposing Internal Structure

LLDeasyInterview freq: high
Choose your preparation mode4 modes available
▶
Class Trace
Step 1/4
Iterator<T> interface

Iterator<T> defines traversal methods without state, enabling OCP for different iteration strategies.

🎯 Tests if candidate understands interfaces cannot hold instance state in Java, so iteration state must be in implementing classes.
public interface Iterator<T> {
    boolean hasNext();
    T next();
}
ConcreteIterator<T> abstract class

ConcreteIterator<T> holds iteration state (aggregate reference, currentIndex) and synchronizes traversal methods.

🎯 Tests why abstract class is used over interface: to hold mutable state and provide synchronized methods for thread safety.
public abstract class ConcreteIterator<T> implements Iterator<T> {
    protected final Aggregate<T> aggregate; // association
    protected int currentIndex = 0;
    public synchronized boolean hasNext() {
        // thread-safe check of currentIndex vs aggregate size
    }
    public synchronized T next() {
        // thread-safe retrieval or throw NoSuchElementException
    }
}
ConcreteAggregate<T> composition

ConcreteAggregate<T> owns a List<T> collection (composition) and creates ConcreteIterator instances.

🎯 Tests understanding of composition lifecycle: ConcreteAggregate owns items list, so items cannot exist independently.
public class ConcreteAggregate<T> implements Aggregate<T> {
    private final List<T> items = new ArrayList<>(); // composition
    public Iterator<T> createIterator() {
        return new ConcreteIterator<T>(this);
    }
}
NoSuchElementException usage

ConcreteIterator throws NoSuchElementException when next() is called with no remaining elements.

🎯 Tests if candidate knows Java standard unchecked exception usage to signal iteration end, avoiding null returns.
public class ConcreteIterator<T> implements Iterator<T> {
    public synchronized T next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        // return next element
    }
}
📐
Class Diagram
Class Diagram
       +----------------------+
       | <<Interface>>        |
       | Iterator<T>          |
       |----------------------|
       | + hasNext(): boolean |
       | + next(): T          |
       +----------------------+
               ─ ─ ─►
       +----------------------+
       | <<Abstract>>         |
       | ConcreteIter<T>      |
       |----------------------|
       | - aggr: Aggregate<T> |
       | - currIdx: int       |
       |----------------------|
       | + hasNext(): boolean [sync] |
       | + next(): T [sync]           |
       +----------------------+
               │ extends
       +----------------------+
       | <<Interface>>        |
       | Aggregate<T>         |
       |----------------------|
       | + createIterator(): Iterator<T> |
       +----------------------+
               ─ ─ ─►
       +----------------------+
       | ConcreteAggr<T>      |
       |----------------------|
       | - items: List<T>     |
       |----------------------|
       | + createIterator(): Iterator<T> |
       +----------------------+
               ─ ─ ─►
       +----------------------+
       | NoSuchElementException|
       |----------------------|
       | + NoSuchElementException() |
       +----------------------+

This class diagram illustrates the Iterator pattern in Java focusing on key design decisions. The Iterator<T> interface defines traversal methods without state, enforcing OCP by allowing multiple implementations. ConcreteIterator<T> is an abstract class holding iteration state such as currentIndex and a reference to the Aggregate, using synchronized methods to ensure thread-safe iteration. ConcreteAggregate<T> composes a List<T> collection, owning its lifecycle, and creates ConcreteIterator instances via a factory method, demonstrating composition. The use of NoSuchElementException in ConcreteIterator's next() method follows Java conventions for signaling iteration end without returning null. These decisions highlight Java-specific mechanisms like interface limitations on state, abstract class state holding, synchronized methods for concurrency, and exception handling for robust iteration.

Primary Focus

✓ Abstract class vs Interface + Composition lifecycle + Realization + Exception usage

Practice

(1/5)
1. In a Wallet System design, the Transaction class has a private constructor and a static synchronized getInstance() method that returns the single instance. Which design pattern is applied here and why is this the correct use case?
easy
A. Factory Method pattern, because it controls object creation with a static method.
B. Singleton pattern, ensuring only one Transaction instance exists to maintain consistency.
C. Builder pattern, to construct complex Transaction objects step-by-step.
D. Prototype pattern, to clone existing Transaction instances efficiently.

Solution

  1. Step 1: Identify the pattern from constructor and method signatures

    The private constructor prevents external instantiation, and the static synchronized getInstance() method ensures a single instance is created and accessed thread-safely.
  2. Step 2: Why Singleton fits this Wallet Transaction scenario

    Singleton is appropriate when exactly one instance is needed to coordinate actions or maintain global state, such as a ledger manager or transaction coordinator. Factory Method and Builder patterns do not enforce single instance, and Prototype is for cloning, not restricting instances.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Private constructor + synchronized static getInstance() -> Singleton pattern [check]
Hint: Private constructor + static synchronized method -> Singleton [check]
Common Mistakes:
2. You want to add a WeekendFeeStrategy to calculate parking fees differently on weekends. According to SOLID principles, what is the minimum change required in the current Abstract Factory design?
medium
A. Add a boolean weekend flag to ParkingLot and modify fee calculation accordingly.
B. Create a new WeekendFeeStrategy class implementing FeeStrategy and inject it without modifying existing classes.
C. Combine all fee strategies into one class with multiple methods for each pricing rule.
D. Modify the existing FeeStrategy class to add weekend logic with if-else checks.

Solution

  1. Step 1: Identify SOLID principle involved

    Open-Closed Principle (OCP) requires new functionality added via extension, not modification.
  2. Step 2: Evaluate options

    Create a new WeekendFeeStrategy class implementing FeeStrategy and inject it without modifying existing classes. respects OCP by adding a new class without modifying existing ones. Add a boolean weekend flag to ParkingLot and modify fee calculation accordingly. modifies ParkingLot, violating OCP. Options A and D modify existing classes, violating OCP.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New strategy class added, existing classes unchanged [check]
Hint: OCP: extend with new class, don't modify existing ones [check]
Common Mistakes:
3. In the Stack Overflow voting system, if the castVote() method is not synchronized, which exact sequence of thread interleaving causes a double vote count for the same user on a question?
medium
A. Thread 1 reads vote count, Thread 2 reads vote count, both increment and write back simultaneously
B. Thread 1 checks if user has voted -> false, context switch; Thread 2 checks if user has voted -> false; both proceed to cast vote
C. Thread 1 updates vote count, Thread 2 waits; Thread 1 finishes, Thread 2 updates vote count again
D. Thread 1 and Thread 2 both block on the same lock, causing deadlock

Solution

  1. Step 1: Identify the check-then-act race condition

    The critical issue is the check if the user has already voted. Without synchronization, both threads see no vote recorded and proceed.
  2. Step 2: Trace exact interleaving causing double vote

    Thread 1 checks voted -> false, context switch; Thread 2 checks voted -> false; both cast votes, causing double count.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Check-then-act gap without sync -> double vote [check]
Hint: Check-then-act gap -> double vote without sync [check]
Common Mistakes:
4. To support ElectricCar and ChargingSpot in the existing parking system using Chain of Responsibility, what is the minimum change that respects extensibility and avoids modifying existing classes?
hard
A. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility.COMPATIBILITY_MAP accordingly.
B. Modify Vehicle and Spot classes to add boolean isElectric and isChargingSpot flags, then update existing handlers to check these flags.
C. Create a new ElectricCarHandler in the chain that handles electric cars and charging spots, modifying the chain setup to include it.
D. Add a new method in Vehicle interface for charging compatibility and implement it in ElectricCar, modifying existing handlers to call it.

Solution

  1. Step 1: Identify extensibility requirements

    Adding ElectricCar and ChargingSpot should not require modifying existing classes to avoid breaking OCP.
  2. Step 2: Evaluate options

    Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility.COMPATIBILITY_MAP accordingly. modifies enums and compatibility map, changing existing code; Modify Vehicle and Spot classes to add boolean isElectric and isChargingSpot flags, then update existing handlers to check these flags. adds flags and updates handlers without changing existing class hierarchies; Create a new ElectricCarHandler in the chain that handles electric cars and charging spots, modifying the chain setup to include it. modifies chain setup, which is acceptable but may require modifying chain initialization; Add a new method in Vehicle interface for charging compatibility and implement it in ElectricCar, modifying existing handlers to call it. modifies Vehicle interface, breaking existing implementations.
  3. Step 3: Choose minimal invasive approach

    Modify Vehicle and Spot classes to add boolean isElectric and isChargingSpot flags, then update existing handlers to check these flags. adds minimal changes with flags and updates handlers, avoiding class explosion or interface changes.
  4. Final Answer:

    Option B -> Option B
  5. Quick Check:

    Flags added, existing classes unchanged, handlers updated [check]
Hint: Add flags and update handlers, avoid modifying classes [check]
Common Mistakes:
5. The system needs to support ElectricCar and ChargingSpot without modifying existing classes. What is the minimum change to the current design to support this?
hard
A. Create a new ElectricCar class and ChargingSpot class, then modify Cart and Order to handle them explicitly.
B. Modify Vehicle class to add isElectric flag and add logic for charging spots inside existing methods.
C. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, update SpotCompatibility map; no existing class changes.
D. Add a new interface Chargeable and implement it in ElectricCar and ChargingSpot, modifying existing classes to check for it.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Adding new enum values and new subclasses allows extension without changing existing class code.
  2. Step 2: Update SpotCompatibility map to include new types

    Updating compatibility map is a configuration change, not a class modification, preserving OCP.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Enum extension + new subclasses + compatibility map update -> no existing class change [check]
Hint: Extend enums + subclasses + config map -> no class edits [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard