Java Project: Session Report
Turn a collection of accepted bookings into a deterministic seat report. Group by session, add the seat counts and print session names in a predictable order.
Your brief
A report should state which records are included and what each number means. These records are already accepted bookings, so the aggregation does not decide capacity or validate payments. Use an immutable record for each row and a sorted map for the output contract. Counting bookings and counting seats answer different questions; a two-person booking contributes one booking but two seats. Keep that distinction visible in method and variable names. For larger imports, validate and reject malformed input before this aggregation stage.
Run it locally
Use a local JDK 21 or newer. Save the complete example as Main.java in a separate lab folder, then compile and run it with the commands below. Java examples do not run in Bhylu’s browser playground. The -ea option enables assertion checks used by some lessons.
javac --release 21 -encoding UTF-8 -d out Main.java
java -ea -cp out MainWorked solution
Show the worked solution
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class Main {
record Booking(String session, int seats) {
Booking {
if (session == null || session.isBlank() || seats <= 0)
throw new IllegalArgumentException("Invalid booking");
}
}
public static void main(String[] args) {
List<Booking> bookings = List.of(new Booking("Clay", 2), new Booking("Print", 3), new Booking("Clay", 1));
Map<String, Integer> seats = new TreeMap<>();
for (Booking booking : bookings) seats.merge(booking.session(), booking.seats(), Math::addExact);
seats.forEach((session, total) -> System.out.println(session + ": " + total));
if (!seats.equals(Map.of("Clay", 3, "Print", 3))) throw new AssertionError("Wrong report");
}
}
Expected output
Clay: 3
Print: 3TreeMap sorts the session keys for stable output. merge uses the first count directly and calls Math.addExact for later counts under that key. An overflow becomes an explicit failure instead of a wrapped negative total. Record construction validates each row before aggregation. The final comparison checks the complete result, not merely the number of groups.
Extend and test
Add a session with no bookings using a separate session catalogue. Decide whether it should appear as zero, and test that policy. Next produce the same totals with groupingBy and compare both maps.
Check the official Java documentation for detailed contracts and supported options.