【Java】findRooms関数
概要
ホテル予約サイトを開発しており、findRooms関数という「指定したチェックイン / アウト日に利用可能な部屋を見つける」ための関数を作った。作っているうちに、全体像がわからなくなってきたので、頭の整理も兼ねてzenn記事を作成する。コードの全体像は、末尾に記載する。
コード解説
ジェネリクス
public Collection<IRoom> findRooms(Date checkInDate, Date checkOutDate)
まず最初に、IRoomをジェネリック型として使う。IRoomは以下のように、部屋番号、値段、部屋タイプ、無料かどうかといった条件を取得できる。ジェネリクスを使うことで、型を指定できるので、実行時のエラーリスクを減少させられる。
public interface IRoom {
String getRoomNumber();
Double getRoomPrice();
RoomType getRoomType();
boolean isFree();
}
使用可能な部屋
Collection<IRoom> availableRooms = new ArrayList<>();
(中略)
return availableRooms;
次に、使用可能な部屋を格納するための配列を作成する。予約検索した際、使用可能な部屋があれば、この配列に追加される。最後に、使用可能な部屋を追加した値について、returnされる。
roomListのfor loop文
for (Room room : roomList){
boolean isAvailable = true;
(中略)
if (isAvailable) {
availableRooms.add(room);
}
上記のroomListとは、下記コードにて、追加された部屋タイプのこと。ここのloopでは、それぞれのloopに対して、予約チェックをしに行く(後述)構図となっている。まずは、isAvailable(利用可能)がtrueとなっている。そして、これがtrueであれば、利用可能な部屋として、部屋が追加される仕組みとなっている。追加されれば、最後にユーザがチェックイン、チェックアウト日を指定した時に、「この日程だと、この部屋空いてますよ」っていった感じで、部屋追加がされる。
public void addRoom(String roomNumber, Double price, RoomType roomType) {
boolean roomExists = roomList.stream().anyMatch(room -> room.getRoomNumber().equals(roomNumber));
if (!roomExists) {
Room newRoom = new Room(roomNumber, price, roomType);
roomList.add(newRoom);
System.out.println("Room added successfully: " + roomNumber);
} else {
System.out.println("Room with number " + roomNumber + " already exists.");
}
}
reservationのloop文
各部屋に対して、保管された予約リストをチェックしていく形となる。
for (Reservation reservation : reservations) {
if (reservation.getRoom().equals(room)) {
if ((checkInDate.before(reservation.getCheckOutDate()) && checkInDate.after(reservation.getCheckInDate())) || (checkOutDate.after(reservation.getCheckInDate()) && checkOutDate.before(reservation.getCheckOutDate()))) {
isAvailable = false;
break;
}
if (reservation.getRoom().equals(room))という条件文では、特定の予約の部屋が、今loopしている部屋と同じかってことをチェックしている。
そしてその次のチェックイン、チェックアウト日のチェックについて、
・入力されたチェックイン日が、「予約リストのチェックアウト日より前」で「チェックイン日より後」
もしくは
・入力されたチェックアウト日が、「予約リストのチェックイン日より後」で「チェックアウト日より前」
であった場合、isAvailableがflaseとなる。そうすることで、予約可否をチェックできる。
全体の流れの復習
前提条件
部屋タイプ:シングル、ダブル
予約リスト:
・シングル:1/1~1/3, 1/5~1/8
・ダブル:1/3~1/4, 1/6~1/9
ユーザの入力日:1/3~1/5
流れ
// ここでユーザがチェックイン日を1/3、チェックアウト日を1/5で入力
public Collection<IRoom> findRooms(Date checkInDate, Date checkOutDate) {
// availableRoomsという配列が作られる。
Collection<IRoom> availableRooms = new ArrayList<>();
// roomListは、addRoom関数でシングルタイプ、ダブルタイプが追加される。
// それぞれのroomに対して、loopをかける。
// シングルタイプ、ダブルタイプの順でloopを事項するイメージ
// ToDo: 実際に追加されているか確認する。
for (Room room : roomList){
// 最初はisAvailableがtrueになっている。
// trueだと、予約可能な部屋として、availableRoomsに追加される。
// そのためのチェックを次のloop文でやる
boolean isAvailable = true;
// ここでは、シングルタイプ、ダブルタイプの順で、部屋が予約されているかチェックをする。
// reservationsには、customer, room, checkInDate, checkOutDateといった形で、予約リストが格納されている。
for (Reservation reservation : reservations) {
// これらの予約リストについて、もしloop中の部屋タイプ(シングルorダブル)と一緒であれば、チェックを行う。
if (reservation.getRoom().equals(room)) {
// 実際のloop条件で確認する。ユーザは1/3~1/5と入力。
// シングル:1/1~1/3, 1/5~1/8なのでok。
// ダブル:1/3~1/4, 1/6~1/9なのでng。
// ToDo: ロジック考える
if ((checkInDate.before(reservation.getCheckOutDate()) && checkInDate.after(reservation.getCheckInDate())) || (checkOutDate.after(reservation.getCheckInDate()) && checkOutDate.before(reservation.getCheckOutDate()))) {
// ToDo: ここ修正。ok、ngなものの処理が違うかも
isAvailable = false;
break;
}
}
// 最後に、isAvailableなものについては、availableRoomsとして追加される。
if (isAvailable) {
availableRooms.add(room);
}
}
}
// availableRoomsに追加されたものがreturnされる。
return availableRooms;
}
ToDo
- if ((checkInDate.before等の条件チェックを確認する。自分が意図した通りに、チェックがかかっていないかも
- 上記のチェックで、ok / ngだった時の処理内容が合っていないかも。ここのチェックも確認する。
- 上記完了後、実際にテストデータを追加して、想定通りに動くか確認する。上記例だと、シングルタイプのみが返ってくるはず。
- 間違っていた場合、以下の通り作業
- roomListで、シングルとダブルタイプがあるか
- reservationsで、上記例の3つの予約が入っているか
- if ((checkInDate.beforeのチェックが機能して、想定通りにtrueかfalseを返しているか
- その後、availableRoomsに格納する / しないものをしっかり整理できているか
コード全体
public Collection<IRoom> findRooms(Date checkInDate, Date checkOutDate) {
Collection<IRoom> availableRooms = new ArrayList<>();
for (Room room : roomList){
boolean isAvailable = true;
for (Reservation reservation : reservations) {
if (reservation.getRoom().equals(room)) {
// 予約した部屋が、reservationsに含まれているか
// その予約したreservationsとユーザ入力のcheckindateとcheckoutdateが正しく比較されているか
// 比較の結果が、availableroomsに格納される仕組みになっているか
if ((checkInDate.before(reservation.getCheckOutDate()) && checkInDate.after(reservation.getCheckInDate())) || (checkOutDate.after(reservation.getCheckInDate()) && checkOutDate.before(reservation.getCheckOutDate()))) {
isAvailable = false;
break;
}
}
if (isAvailable) {
availableRooms.add(room);
}
}
}
return availableRooms;
}
Discussion