Step 8: catalog reports with streams
EnumMap iterates in the enum's declaration order and TreeMap in sorted key order, so every report line is the same on every run.
Build a small library system step by step: enums for fixed rules, records for data, a sealed interface for results, collections for state, Optional for lookups, exceptions for errors, java.time for due dates and fines, and streams for reports, ending in one runnable file you can extend.
Change the code and press Run (Ctrl+Enter). Try to predict the output first, then break it on purpose and read the error. Your edits are saved and match the lesson page.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Extension 1, reservations: when no copy is left, put the member in a first-come, first-served queue for that ISBN; on return, hand the copy to the first member waiting instead of putting it back on the shelf.
Extension 2, rules: add a GUEST member type (1 book for 7 days) and cap any single fine at 200. Print the due date for each member type and the fine for 0, 3 and 30 days late.
Extension 3, report: return the top N most borrowed titles from a borrow history, highest count first, ties broken alphabetically.
Extension 4, concurrency: 100 tasks on an 8-thread pool all try to borrow the last copy of one book. Make sure exactly one succeeds.
Explain it without notes
Why are Book, Member and Loan records, while Library is a normal class?
Why does borrow return a sealed result for a refused borrow but throw an exception for an unknown ISBN?
Why does the program pass dates in instead of calling LocalDate.now()?
How would you make this library safe for many threads borrowing at once?
Which collections did you choose for the catalog, copy counts and loans, and why?
Expected output
by genre: {FICTION=[Dune, Children of Dune, Contact], SCIENCE=[Cosmos, The Gene], HISTORY=[SPQR]}
oldest: Dune (1965)
2+ books: [Herbert, Sagan]
'dune': [Children of Dune, Dune]
years: 1965-2016, 6 books