How do you model a one-to-many relationship in LLD Java classes?
Fast recall
Quick revision
Core answer
Understanding of composition relationships and how to represent them in code using collections, along with proper encapsulation practices.
Exposing the raw List directly via a getter, allowing external code to modify the internal collection without the parent class knowing, breaking encapsulation.
Mention defensive copying or returning unmodifiable collections using Collections.unmodifiableList or List.copyOf to prevent external modification of internal state.
Interview-ready guide
Interview answer
I model a one-to-many relationship by putting a collection field on the one side. So a ParkingLot has a list of ParkingFloor objects, and each ParkingFloor has a list of ParkingSpot objects. The lot is the one, the floors are the many, and the list lives on the lot.
The important boundary is how that collection is exposed. The naive approach is a getFloors method that just returns the internal list directly. The problem is that now any caller can reach in and call clear or add on your private list, and your object's internal state gets corrupted without it knowing. That breaks encapsulation.
So instead I provide controlled mutators — an addFloor method that can validate the input, reject nulls, enforce limits — and the getter returns an unmodifiable view using Collections.unmodifiableList. Callers can iterate and read all they want, but if they try to mutate the returned list, they get an exception, and they can never touch the real one. Mutation only happens through my methods, which is exactly where I can enforce invariants. It's really just encapsulation applied to collections: expose the data for reading, but keep all the changes behind methods you control. The same idea scales to many-to-many, where you'd typically introduce a join entity rather than cross-referencing lists.
For example, a ParkingLot object can own floorA and floorB. Calling lot.addFloor(floorA) validates the floor id and updates the relationship, while lot.getFloors() lets callers inspect the children without clearing or replacing the lot's internal collection.
How do you model a one-to-many relationship in LLD Java classes
Direct Answer
Use a collection field in the 'one' side: ParkingLot has a List of ParkingFloor objects, and ParkingFloor has a List of ParkingSpot objects. Provide controlled access methods like addFloor, removeFloor, and getFloors that return unmodifiable views to protect internal state.
Deep Dive & Architecture
Ownership and multiplicity
In a one-to-many relationship, one object keeps references to several related objects. A ParkingLot can own a List<ParkingFloor>, while every floor has one owning lot. The model should also decide whether a child may move between parents and whether it can exist without its parent.
The collection follows the invariant
Use a List when order matters, a Set when duplicates must be rejected, or a Map when children are normally found by an identifier. For example, a floor can keep Map<SpotId, ParkingSpot> when allocation repeatedly looks up a spot by id.
Mutation stays with the owner
Methods such as addFloor and removeFloor can reject nulls, prevent duplicate ids, and update the child's parent reference when the relationship is bidirectional. A getter should return a read-only view or a copy rather than the live collection. This keeps callers from bypassing the rules by calling clear() or inserting an invalid child directly.
Common Mistakes & Pitfalls
- Returning the live
List— any caller can mutate your internal state. - No controlled add/remove — mutation should be a method that can validate.
- Putting the collection on the wrong side — the one holds the collection of many.
- Exposing setters for the whole list — replace controlled adds, not bulk
setFloors.
Check your understanding
Answer these without looking back at the article.
- What are enums useful for in LLD and how do you use them?
- How do you define the responsibilities of each class in an LLD?
- What is the difference between an abstract class and an interface in LLD?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.