クラスを理解するための例題(2)
例題3:クラスを使うことが有用なケース
では次の要件を考えてみましょう。
例題3
クラスの学級委員であるpaiza君は、クラスのみんなに次のような形式でアカウントの情報を送ってもらうよう依頼しました。
名前 年齢 誕生日 出身地
この情報を扱いやすくするために、年齢が昇順になるようにデータを並び替えることにしました。
クラスメートの情報が与えられるので、並び替えた後のデータを出力してください。
入力値は以下のように与えられます。
N n_1 o_1 b_1 s_1 ... n_N o_N b_N s_N
-
1行目では、paiza君のクラスの人数
Nが与えられます。 -
続く
N行のうちi行目(1 ≦ i ≦ N)では、i番の生徒の名前・年齢・誕生日・出身地を表す整数・文字列n_i ,o_i ,b_i , s_iが順に半角スペース区切りで与えられます。
また条件は以下のようになっています。
-
1 ≦ N ≦ 10 -
n_i , b_i (1 ≦ i ≦ N)は1文字以上20文字以下の文字列 -
b_i (1 ≦ i ≦ N)はMM/DD形式の文字列(例:1月2日→01/02、12月31日→12/31) -
1 ≦ o_i ≦ 100 -
o_i (1 ≦ i ≦ N)は重複することがないことが保証されている。
期待される出力は以下の形です。
n_1 o_1 b_1 s_1 ... n_N o_N b_N s_N
各クラスメートの情報を年齢が昇順になるように整列したのち、入力と同様の形式で出力してください。
この問題の場合、このままの実装方法だと少し困難ですね。
現状だと、生徒の属性がそれぞれ個別のリストに保存されており、各生徒はそのインデックスで表現されていたため、あるリストを並べ替えてしまった場合、その他のリストがその順序を追従せねばなりません。不可能ではないと思いますが、それぞれの属性をバラバラに保存しておくのは少し問題がありそうです。生徒のデータは生徒ひとりを表すデータ構造にまとめたほうが楽に扱えそうですね。
では生徒ひとりを表すStudentクラスを作って使ってみましょう。
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
var sc = new Scanner(System.in);
IntStream
.range(0, sc.nextInt())
.mapToObj(i -> new Student(sc.next(), sc.nextInt(), sc.next(), sc.next()))
.sorted(Comparator.comparing(Student::getOld))
.forEach(System.out::println);
}
static class Student {
private String nickname;
private int old;
private String birth;
private String state;
Student(String nickname, int old, String birth, String state) {
this.nickname = nickname;
this.old = old;
this.birth = birth;
this.state = state;
}
int getOld() {
return old;
}
@Override
public String toString() {
return nickname + " " + old + " " + birth + " " + state;
}
}
}
と、このようになります。今回使用しないメソッドについては省略してしまいましたが、いかがでしょうか。入力値を基にStudentインスタンスを作成し、getOldメソッドの結果をもって昇順に並び替え、それらを順番に出力しています。クラスを作成し、それを使用することで比較的理解しやすいコードになったのではないでしょうか。
おわりに
クラスを自由に作り、使えるようになると、よりわかりやすいコードが記述できるようになります。
paizaラーニングでは、設計や実装経験の場数を補うため、クラス・構造体を利用すべき場面や処理について理解を深めることを目的としたクラス・構造体メニューという問題集を作成しました。このクラス・構造体メニューの対象者は、クラスの概念・関連する文法は理解していて、小規模なプログラムは書けるようになってきた人や、重めのシミュレーション問題を解けるようになりたい人です。適切なアクセス制限、段階的にクラス・構造体を拡張させていく実装経験を積むことができるような構成になっており、アクセス制限、オーバーロード、継承、などについて実装経験を通じて理解を深めていくことができます。
この問題集は大きく3つのセクションに分かれています。各セクションは、1つの「ボス問題」といくつかの「準備問題」によって構成されています。
1つ目のセクションでは「構造体」を、 2つ目のセクションでは「クラス」を扱います。3つ目は、1つ目と2つ目のセクションで学んだことをもとにクラス・構造体の実践問題を解くセクションとなっています。
クラス・構造体の理解を深めるには、できるだけ多くの問題に触れ、しっかりとした知識を得る必要があります。じっくりと時間をかけて、順番に取り組んでいただけたら嬉しいです。
解説や解答コード例も参考にぜひ何度もチャレンジして力をつけていってくださいね。
