SwadhyAI Notes

All Low-Level Design notes

Behavioral · Gang of Four

Iterator

Iterator is a behavioral pattern that walks a collection without exposing how it is stored. Clients ask for the next element; they do not dig into floors and lists by hand.

Example: a parking lot has floors, and each floor has spots. A report wants every free EV spot. If the report writes lot.getFloors().get(i).getSpots(), it owns the shape of the lot. An iterator (or a stream from the lot) hides that shape.

One walk

The cursor, not the list

Iterator is a . The creates it. The caller never sees Floor. That is encapsulation, not a clever data structure. Collections-ownership says the lot owns the spots. Iterator is how you let people look without lending them the list.

  1. 1EV-1next()
  2. 2EV-2next()
  3. 3STD-3next()
  4. 4STD-4next()
  5. 5STD-5next()
  6. 6EV-6next()

Returning the internal list

getSpots() that returns the live ArrayList is not an iterator. Callers will sort it, remove from it, and store it. Either copy, wrap as unmodifiable, or hand out an iterator. See encapsulation.

Leaking Node

An iterator whose next() returns a linked-list Node with .prev and .next has not hidden structure. Next should be the domain object: ParkingSpot, File, Cell.

Java: spots without exposing floors

Implement so for-each works. The anonymous iterator holds two indices. A parking lot report can filter EV spots without knowing Floor exists.

java
interface SpotIterator {
  boolean hasNext();
  ParkingSpot next();
}

class LotSpots implements Iterable<ParkingSpot> {
  private final List<Floor> floors;

  public Iterator<ParkingSpot> iterator() {
    return new Iterator<>() {
      int f = 0, s = 0;

      public boolean hasNext() {
        while (f < floors.size()) {
          if (s < floors.get(f).spotCount()) return true;
          f++;
          s = 0;
        }
        return false;
      }

      public ParkingSpot next() {
        if (!hasNext()) throw new NoSuchElementException();
        return floors.get(f).spot(s++);
      }
    };
  }
}

// for (ParkingSpot spot : lot.spots()) { ... }

When the walk is not a List

Floors of spots

Flatten in the iterator. The lot can skip a closed floor without the report changing.

File tree

A Composite can offer depth-first and breadth-first iterators without exposing Node.

Occupied squares

A chess board can iterate occupied squares. Callers never see the 8×8 array.

One iterator, one walk. Do not mutate the collection under the iterator unless you have a story. Java’s ConcurrentModificationException is that story.

Live list, copy, or iterator?

Three doors, three failure modes. Pick one and say why. Returning the live ArrayList is the default bug in parking-lot rounds.

DoorCaller canUse when
Live listclear(), sort, stash a referenceAlmost never in LLD
Unmodifiable copyRead a snapshot, not mutate yoursSmall collections, random access
Iterator / IterableWalk once; no structureNested floors, trees, huge walks

Java: skip closed floors without leaking Floor

hasNext advances both indices. A closed floor is a continue, not a type the report must know.

java
public boolean hasNext() {
  while (f < floors.size()) {
    Floor floor = floors.get(f);
    if (floor.isClosed()) { f++; s = 0; continue; }
    if (s < floor.spotCount()) return true;
    f++;
    s = 0;
  }
  return false;
}

Fail-fast is a feature

If park() adds a spot while a report iterates, throw. Silent skip is worse. Snapshot the free list if the report must be stable.

Two iterators, two algorithms

Depth-first and breadth-first on a file tree are two iterator types. The Node type still stays private.

How to explain this in an interview

“The lot owns floors. The report walks spots. If a floor closes, the iterator skips it and the report does not change.” That rule is the pattern. getSpots() returning ArrayList is the anti-pattern. One iterator, one walk; mutating under it should fail fast.

Nearby in LLD