Bird
Raised Fist0

Iterator Pattern - Traversal Without Exposing Internal Structure

LLDeasyInterview freq: high
Choose your preparation mode4 modes available
🏗️
Iterator Pattern - Traversal Without Exposing Internal Structure
Provide a way to access elements of a collection sequentially without exposing its underlying representation.
easyDesign Patterns - AppliedFreq: high
Prerequisites:OOP BasicsJava Interfaces and Abstract ClassesCollections Framework
⚙️
Functional Requirements
  • Provide an Iterator interface with methods hasNext() and next().
  • Aggregate interface must provide a method to create an Iterator.
  • ConcreteAggregate implements the Aggregate interface and maintains the collection.
  • ConcreteIterator implements Iterator and maintains traversal state privately.
  • Iterator must not expose internal collection structure or allow modification during traversal.
  • Support multiple concurrent iterators on the same collection safely.
  • Iterator should throw NoSuchElementException if next() is called when no elements remain.
👤
Use Cases
  • Client requests an iterator to traverse a collection without accessing its internal structure.
  • Client uses the iterator to sequentially access elements.
  • Multiple clients concurrently traverse the same collection safely.
  • Extend collection types with custom iterators without modifying existing code.
  • Support resetting the iterator to the start of the collection.
🧑‍💻
Actors
  • Client
  • ConcreteAggregate
  • ConcreteIterator
❓
Clarifying Questions to Ask
  • How many threads or clients will concurrently traverse the collection?
  • Should the iterator support modification of the underlying collection during traversal?
  • Is the collection fixed size or can it change during iteration?
  • Are there any performance constraints on iterator creation or traversal?
  • Should the iterator support reset or restart functionality?
  • What exceptions should be thrown on invalid iterator operations?
  • Is there a pricing or resource usage strategy for creating multiple iterators?
Out of Scope
✗ Modification operations on the collection via iterator (e.g., remove()).
✗ Bidirectional or random access iterators.
✗ Concurrent modification detection (fail-fast behavior).
✗ Persistence or serialization of iterators.
🔢
Enumerations
enum IteratorState
NOT_STARTED | IN_PROGRESS | COMPLETED
Defines the traversal state of the iterator to manage lifecycle and prevent invalid next() calls. Using enum prevents typo bugs and enables exhaustive switch statements.
enum CollectionType
ARRAY | LINKED_LIST | TREE
Specifies the type of underlying collection to allow different iterator implementations. Enum ensures type safety and clear branching.
📦
Iterator<T>
0 fields
Defines the interface for traversing elements sequentially without exposing the underlying collection structure.
Why thisInterface is used to allow multiple implementations without shared state, fitting Java's multiple interface inheritance.
Why notAbstract classes would force single inheritance and shared state, limiting flexibility.
public boolean hasNext()Returns true if the iteration has more elements.
public T next()Returns the next element in the iteration; throws NoSuchElementException if none.
📦
Aggregate<T>
0 fields
Defines the interface for creating an iterator to traverse its elements.
Why thisInterface allows different collection types to provide their own iterator implementations.
Why notUsing abstract classes would limit the ability to extend multiple collection types.
public Iterator<T> createIterator()Returns an iterator to traverse the aggregate's elements.
📦
ConcreteAggregate<T>
1 fields
private final List<T> items
Implements Aggregate interface; holds the collection and creates ConcreteIterator instances.
Why thisUses Java's synchronized methods to ensure thread safety for concurrent access.
Why notOther concurrency controls like ReadWriteLock add complexity and are unnecessary for simple iteration.
public Iterator<T> createIterator()Returns a new ConcreteIterator instance for this collection.
public synchronized T getItem(int index)Returns the element at the specified index in a thread-safe manner.
public synchronized int getSize()Returns the size of the collection in a thread-safe manner.
📦
ConcreteIterator<T>
3 fields
private final ConcreteAggregate<T> aggregateprivate int currentIndexprivate IteratorState state
Implements Iterator interface; maintains traversal state and accesses elements via ConcreteAggregate without exposing internal structure.
Why thisSynchronized methods ensure safe concurrent traversal without exposing internal state.
Why notUsing volatile or atomic variables alone would not guarantee atomicity of combined operations.
public synchronized boolean hasNext()Checks if more elements are available; synchronized to ensure visibility of currentIndex.
public synchronized T next()Returns next element and advances index; throws NoSuchElementException if none.
public synchronized void reset()Resets the iterator to the initial position.
📦
NoSuchElementException
0 fields
Standard Java exception thrown when next() is called but no elements remain.
Why thisStandard Java exception for iterator boundary violations.
Why notCustom exceptions would add unnecessary complexity.
🔗
Relationships
ConcreteAggregate◆──►List<T>[1 to many]
compositionConcreteAggregate owns the List; list cannot exist independently
ConcreteAggregate──►ConcreteIterator[1 to many]
associationConcreteIterator depends on ConcreteAggregate but can exist independently
ConcreteIterator──►ConcreteAggregate[many to 1]
associationConcreteIterator holds reference to ConcreteAggregate but does not own it
ConcreteIterator──►Iterator[1 to 1]
realizationConcreteIterator implements Iterator interface
ConcreteAggregate──►Aggregate[1 to 1]
realizationConcreteAggregate implements Aggregate interface
🗄️
Collections
PK: collectionId
collectionId: UUIDitemIndex: intitemData: blob
Stores collection items indexed by collectionId and itemIndex for ordered traversal.
🗄️
Iterators
PK: iteratorId
iteratorId: UUIDcollectionId: UUIDcurrentIndex: intstate: IteratorState
Tracks iterator state and position for concurrent traversal.
🔌
CreateIterator
Request
{
  "collectionId": "UUID"
}
Response
{
  "iteratorId": "UUID"
}
Creates a new iterator instance for the specified collection.
🔌
IteratorHasNext
Request
{
  "iteratorId": "UUID"
}
Response
{
  "hasNext": "boolean"
}
Checks if the iterator has more elements.
🔌
IteratorNext
Request
{
  "iteratorId": "UUID"
}
Response
{
  "itemData": "blob"
}
Returns the next element in the iteration; throws error if none.

Practice

(1/5)
1. In designing the Vehicle hierarchy for the booking system's parking module, should Vehicle be an abstract class or an interface, and why?
easy
A. Vehicle should be an interface because it only defines behavior without state.
B. Vehicle should be an abstract class because it holds common state like license plate and enforces shared behavior.
C. Vehicle should be a concrete class to allow direct instantiation of generic vehicles.
D. Vehicle should be an enum to restrict vehicle types strictly.

Solution

  1. Step 1: Identify if common state exists in Vehicle

    Vehicle has shared fields like license plate, size, or type, which require storage and partial implementation.
  2. Step 2: Abstract class fits because it allows shared state and behavior, while interfaces cannot hold instance state.

    Using an abstract class enforces common code reuse and prevents direct instantiation.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Common state + shared behavior -> abstract class [check]
Hint: State needs abstract class; behavior-only needs interface [check]
Common Mistakes:
2. In the Hotel Management System, if the parkVehicle() method is not synchronized, which exact sequence of events between Thread 1 and Thread 2 causes double-booking of the same parking spot?
medium
A. Thread 1 checks spot availability -> true, context switch before marking occupied; Thread 2 checks availability -> true, both park simultaneously.
B. Thread 1 marks spot occupied, Thread 2 reads spot as occupied and waits indefinitely.
C. Thread 1 parks vehicle, Thread 2 waits until Thread 1 finishes, then parks another vehicle.
D. Thread 1 and Thread 2 both crash due to simultaneous access causing deadlock.

Solution

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

    Without synchronization, Thread 1 reads spot as available and is preempted before marking it occupied.
  2. Step 2: Thread 2 also reads spot as available and proceeds to park, causing double-booking.

    This is the classic check-then-act gap causing race condition.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Check availability -> true by both threads before marking occupied -> double-booking [check]
Hint: Check-then-act gap -> double-booking without synchronization [check]
Common Mistakes:
3. In the FollowService, the method followUser() checks if the follower already follows the followee before adding. Without synchronization, which exact thread interleaving causes a double-follow entry?
medium
A. Thread 1 and Thread 2 both wait on a lock, preventing double-follow.
B. Thread 1 reads follower list, Thread 2 removes follower, both add follower again.
C. Thread 1 adds follower, Thread 2 reads follower list after addition, no conflict.
D. Thread 1 checks isFollowing() -> false, context switch, Thread 2 checks isFollowing() -> false, both add follower.

Solution

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

    Both threads call isFollowing() and get false before either adds the follower, due to lack of synchronization.
  2. Step 2: Resulting double addition

    Both threads proceed to add the follower, causing duplicate entries.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Check-then-act gap -> both see false -> both add follower [check]
Hint: Check-then-act without sync -> double add race [check]
Common Mistakes:
4. Adding a WeekendFeeStrategy to calculate weekend parking fees requires which minimum change to the current design that uses a FeeStrategy interface?
medium
A. Combine all fee calculations into one class with if-else for weekend and weekday fees
B. Create a new WeekendFeeStrategy class implementing FeeStrategy and inject it without modifying existing classes
C. Modify the existing FeeStrategy interface to add a isWeekend() method and update all implementations
D. Add a boolean flag isWeekend in ParkingLot and conditionally apply fees inside existing strategies

Solution

  1. Step 1: Understand current design with FeeStrategy interface

    FeeStrategy interface allows different fee calculation implementations, supporting OCP if new strategies are added as new classes.
  2. Step 2: Analyze minimal change for weekend fees

    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 flag isWeekend in ParkingLot and conditionally apply fees inside existing strategies modifies ParkingLot to add weekend logic, violating OCP but minimal change.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Minimal change but violates OCP -> modify ParkingLot with weekend flag [check]
Hint: Minimal change ≠ OCP compliance; adding flag is minimal but not ideal [check]
Common Mistakes:
5. ElectricCar requires ChargingSpots in the parking lot system. What is the minimum change to support this without modifying existing classes?
hard
A. Add a boolean isElectric flag to Vehicle and Spot classes and handle compatibility internally.
B. Modify Vehicle and Spot classes to add electric-specific fields and logic directly.
C. Create a new ElectricParkingLot subclass handling electric vehicles and spots separately.
D. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    To comply with OCP and avoid class explosion, new types should be added via enums and new subclasses without changing existing code.
  2. Step 2: Explain why Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally. fits minimal change

    Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally. adds new enum values and creates a new ElectricCar subclass, updating compatibility externally, preserving existing classes unchanged. Options B, C, and D modify existing classes or create subclasses that duplicate logic, violating OCP or SRP.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    New enums + subclass + external compatibility update -> minimal change [check]
Hint: Add enums + subclass + external map update -> no existing class changes [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