7日目のゴール
7日目のテーマは
「ArrayList を“単なる便利クラス”から、“アプリの中のデータ構造”として意識して使えるようになること」 です。
ここまでであなたはすでに、
ArrayList は伸び縮みする
クラスのフィールドとして持てる
オブジェクトのリストを扱える
検索・更新・削除・並び替えができる
Comparator で並び替えルールを変えられる
というところまで来ています。
7日目では、それらをまとめて、
「現実っぽいアプリの中で ArrayList をどう設計するか」
「どこまでを ArrayList に任せて、どこからを自分のルールにするか」
を、小さな「図書館貸出管理アプリ」を題材にして整理していきます。
今日の題材:図書館の貸出管理ミニアプリ
アプリの世界を言葉で先に決める
まずはコードを書く前に、「世界観」を言葉で決めます。
本がある
利用者がいる
貸出記録がある
この3つが登場人物です。
本は「タイトル・著者・ID」
利用者は「名前・会員番号」
貸出記録は「どの本を・誰が・いつ借りたか」
これらをクラスで表現し、
その「集まり」を ArrayList で管理していきます。
Book・User・Loan をクラスで表現する
Book クラス
public class Book {
String id;
String title;
String author;
Book(String id, String title, String author) {
if (id == null || id.isEmpty()) {
throw new IllegalArgumentException("ID は必須です。");
}
if (title == null || title.isEmpty()) {
throw new IllegalArgumentException("タイトルは必須です。");
}
if (author == null || author.isEmpty()) {
throw new IllegalArgumentException("著者は必須です。");
}
this.id = id;
this.title = title;
this.author = author;
}
void show() {
System.out.println("ID: " + id + " / タイトル: " + title + " / 著者: " + author);
}
}
Javaここで大事なのは、
「本を一意に識別するための ID を持っている」ことです。
タイトルが同じ本があっても、ID が違えば別の本として扱えます。
User クラス
public class User {
String memberId;
String name;
User(String memberId, String name) {
if (memberId == null || memberId.isEmpty()) {
throw new IllegalArgumentException("会員番号は必須です。");
}
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("名前は必須です。");
}
this.memberId = memberId;
this.name = name;
}
void show() {
System.out.println("会員番号: " + memberId + " / 名前: " + name);
}
}
Java利用者も同じく、「会員番号」で一意に識別します。
Loan クラス(貸出記録)
public class Loan {
Book book;
User user;
String date;
Loan(Book book, User user, String date) {
if (book == null) {
throw new IllegalArgumentException("本は必須です。");
}
if (user == null) {
throw new IllegalArgumentException("利用者は必須です。");
}
if (date == null || date.isEmpty()) {
throw new IllegalArgumentException("日付は必須です。");
}
this.book = book;
this.user = user;
this.date = date;
}
void show() {
System.out.println("【貸出】日付: " + date);
System.out.print(" 本: ");
book.show();
System.out.print(" 利用者: ");
user.show();
}
}
Javaここが今日の重要ポイントのひとつです。
Loan は「Book と User を“参照”として持っている」
つまり、
「貸出記録は、本と利用者の“関係”を表すオブジェクト」
になっています。
ArrayList で「集まり」を管理するクラスを作る
Library クラスの役割を決める
Library クラスには、こういう責務を持たせます。
本の一覧を管理する
利用者の一覧を管理する
貸出記録の一覧を管理する
本を登録する
利用者を登録する
本を貸し出す
貸出中の本を一覧表示する
これらを、すべて ArrayList で支えます。
Library クラスのフィールドとコンストラクタ
import java.util.ArrayList;
public class Library {
ArrayList<Book> books;
ArrayList<User> users;
ArrayList<Loan> loans;
Library() {
books = new ArrayList<>();
users = new ArrayList<>();
loans = new ArrayList<>();
}
}
Javaここで大事なのは、
本のリスト
利用者のリスト
貸出記録のリスト
という「3種類の可変長データ」を、
それぞれ別の ArrayList で管理していることです。
本と利用者の登録
本の登録メソッド
void addBook(Book book) {
if (book == null) {
System.out.println("null の本は登録できません。");
return;
}
books.add(book);
}
Java利用者の登録メソッド
void addUser(User user) {
if (user == null) {
System.out.println("null の利用者は登録できません。");
return;
}
users.add(user);
}
Javaここはシンプルですが、
「ArrayList を直接触らず、意味のあるメソッドで操作する」
というこれまでの流れを踏襲しています。
ID で本・利用者を検索する
本を ID で探す
Book findBookById(String id) {
if (id == null || id.isEmpty()) {
return null;
}
for (Book b : books) {
if (b.id.equals(id)) {
return b;
}
}
return null;
}
Java利用者を会員番号で探す
User findUserByMemberId(String memberId) {
if (memberId == null || memberId.isEmpty()) {
return null;
}
for (User u : users) {
if (u.memberId.equals(memberId)) {
return u;
}
}
return null;
}
Javaここで改めて確認したいのは、
ArrayList の中身を「先頭から順番に見る」線形探索
ID や会員番号のような「一意なキー」で探す
というパターンです。
本を貸し出す処理を ArrayList で組み立てる
貸出メソッドの全体像
boolean loanBook(String bookId, String memberId, String date) {
Book book = findBookById(bookId);
if (book == null) {
System.out.println("そのIDの本は存在しません。");
return false;
}
User user = findUserByMemberId(memberId);
if (user == null) {
System.out.println("その会員番号の利用者は存在しません。");
return false;
}
if (isBookOnLoan(book)) {
System.out.println("その本はすでに貸出中です。");
return false;
}
Loan loan = new Loan(book, user, date);
loans.add(loan);
System.out.println("貸出を登録しました。");
return true;
}
Javaここでやっていることを、順番に言葉にします。
ID から本を探す
会員番号から利用者を探す
その本がすでに貸出中かどうかをチェックする
問題なければ Loan を作って、loans に追加する
つまり、
「複数の ArrayList をまたいで、“アプリとして意味のある処理”を組み立てている」
という状態です。
貸出中かどうかを判定するメソッド
boolean isBookOnLoan(Book book) {
for (Loan loan : loans) {
if (loan.book == book) {
return true;
}
}
return false;
}
Javaここでのポイントは、
loan.book == book を使っていることです。
これは「同じ Book オブジェクトかどうか」を参照で比較しています。
ID で比較してもいいですが、
ここでは「同じインスタンスかどうか」で判定しています。
貸出中の本を一覧表示する
loans の中身をそのまま見せる
void showLoans() {
System.out.println("=== 貸出中の本一覧 ===");
if (loans.isEmpty()) {
System.out.println("現在、貸出中の本はありません。");
return;
}
for (Loan loan : loans) {
loan.show();
}
}
Javaここでは、
貸出記録のリスト(ArrayList<Loan>)を
そのまま「ビュー」として使っています。
Loan が Book と User を参照で持っているので、
「Loan を表示するだけで、本と利用者の情報も一緒に見える」
という構造になっています。
Main から見た「アプリとしての顔」
全体を通した利用イメージ
public class Main {
public static void main(String[] args) {
Library lib = new Library();
Book b1 = new Book("B001", "Java入門", "山田太郎");
Book b2 = new Book("B002", "アルゴリズム図鑑", "佐藤花子");
lib.addBook(b1);
lib.addBook(b2);
User u1 = new User("U001", "田中一郎");
lib.addUser(u1);
lib.loanBook("B001", "U001", "2026-05-23");
lib.showLoans();
System.out.println("もう一度同じ本を借りようとしてみる");
lib.loanBook("B001", "U001", "2026-05-24");
}
}
Javaこのコードを眺めてみてください。
Library を作る
本を登録する
利用者を登録する
本を貸し出す
貸出中の本を一覧表示する
Main からは、
「ArrayList」という言葉は一切見えません。
見えているのは、
本
利用者
貸出
図書館
という“アプリの世界”だけです。
裏側では、
本のリスト(ArrayList<Book>)
利用者のリスト(ArrayList<User>)
貸出記録のリスト(ArrayList<Loan>)
という3つの可変長データが、
静かにアプリを支えています。
7日目で整理しておきたい「ArrayList の本質」
ここまで来たあなたに、ArrayList を一言でまとめるなら、
「アプリの中の“増えたり減ったりするもの”を、順番付きで管理するための器」
です。
配列との違いは「伸び縮みする」ことだけではありません。
クラスのフィールドとして持てる
オブジェクトのリストを扱える
検索・更新・削除・並び替えの土台になる
複数の ArrayList を組み合わせて、「世界」を表現できる
7日目で一番大事なのは、
「ArrayList をどう書くか」ではなく、
「ArrayList をどこに置いて、何の“集まり”を表現させるか」
を考えられるようになることです。
もし余裕があれば、今日の Library に
「返却メソッド(loan を削除する)」
「特定の利用者の貸出一覧を表示する」
などを自分で足してみてください。
そのとき、必ず
「どの ArrayList を、どんな条件でなめるか」
を意識することになります。
そこまで行けたら、
あなたはもう「ArrayList を使う側」ではなく、
「ArrayList を前提にアプリの世界を設計する側」 に立っています。

