こんにちは、コンスキです。
インスタンスをArrayListの要素にする時ってありますよね。
このArrayListの要素を、それぞれのインスタンスが持っている変数を使ってソートしてみます。
ソート:並べ替える
インスタンスをソートするスクリプト
スクリプト
下のスクリプトが、ArrayListの要素を並べ替えるスクリプトです。
要素はインスタンスオブジェクトになっています。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class Human {
String name;
int age;
int height;
Human(String name, int age, int height) {
this.name = name;
this.age = age;
this.height = height;
}
//変数nameを表示する関数を定義する
void sayName() {
System.out.print(name);
}
}
class Main {
public static void main(String[] args) {
Human human1 = new Human("コ太郎", 12, 150);
Human human2 = new Human("ン太郎", 8, 127);
Human human3 = new Human("ス太郎", 14,165);
Human human4 = new Human("キ太郎", 10, 140);
ArrayList<Human> humans = new ArrayList<Human>();
// ArrayListにhuman1~human4を追加する
humans.add(human1);
humans.add(human2);
humans.add(human3);
humans.add(human4);
//並べ替える前
System.out.println("▼並べ替える前");
for (int i=0; i<humans.size(); i++) {
humans.get(i).sayName(); //human1~human4が持っている変数nameを表示
System.out.print(" "); //見やすくするためにスペースを空ける
}
System.out.print("\n\n");//見やすいように改行
//要素の並べ替え方を決める
Comparator<Human> comparator = new Comparator<Human>() {
@Override
public int compare(Human O1, Human O2) {
Integer o1 = O1.age;
Integer o2 = O2.age;
Integer judgement = Integer.valueOf(o1).compareTo(Integer.valueOf(o2));
return judgement;
}
};
Collections.sort(humans, comparator); //sortメソッドの第2引数に並べ替え方を渡す
//並べ替えた後
System.out.println("▼並べ替えた後");
for (int i=0; i<humans.size(); i++) {
humans.get(i).sayName();
System.out.print(" "); //見やすくするためにスペースを空ける
}
並べ替えでは、インスタンスオブジェクトが持つ変数「age」を基準にしています。
実行結果
実行結果は次のようになります。
▼並べ替える前
コ太郎 ン太郎 ス太郎 キ太郎
▼並べ替えた後
ン太郎 キ太郎 コ太郎 ス太郎
説明
わかりづらくて申し訳ないですが、図にしてみると次のようになります。
確認
並べ替えが正しくできたか手動で確認してみます。
human1~human4の変数ageは
human1: 12 human2: 8 human3: 14 human4: 10
human1~human4の変数nameは
human1: コ太郎 human2: ン太郎 human3: ス太郎 human4: キ太郎
そのため、ageが小さい順番に並べ替えると「human2, human4, human1, human3」です。
順番は変えずにこれらが持っている変数nameを書くと「ン太郎 キ太郎 コ太郎 ス太郎」
「ン太郎 キ太郎 コ太郎 ス太郎」は実行結果にある並べ替えた後の部分と一致します。
正しく並べ替えられていることがわかりました。
問題点:sortメソッドだけではできない
「ArrayList ソート」や「ArrayList 並べ替える」と検索するとまず次のやり方が出てきます。
Collections.sort(ArrayListオブジェクト);
sortメソッドを使うと要素を昇順または降順で並べ替えられます。
しかし、これができるのは要素がString型やint型などである時に限られます。
要素がインスタンスの時はソートできません。
その理由は、String型とint型は並べ替える時の基準があるのに対して、インスタンスには基準がないためです。
例えば、とあるArrayListを昇順で並べ替えたいのことを考えます。
要素がString型とint型であれば、それぞれ次のような並べ替えの基準があります。
String型 ▶︎ アルファベット順のどこにあるかという基準 昇順の例:d, a, f, w, i, g → a, d, f, g, i w
int型 ▶︎ 値の大きさという基準 昇順の例:4, 1, 9, 7, 2, 15 → 1, 2, 4, 7, 9, 15
一方で、インスタンスはどうでしょうか。
文字列でないのでアルファベットを基準にすることも、値の大きさを基準にすることもできません。
解決策
問題を解決するために次のようにします。
並べ替え方の設定「comparator」を作る▶︎sortメソッドの第2引数にcomparaterを渡す
自分で並べ方のルールを作って、sortメソッドを使うときにそのルールを教える感じです。
並べ方のルールを作る
インスタンス自体ではなく、インスタンスが持つ変数を並べ替えの基準に使います。
要素を小さい順に並べたい場合は
Comparator<T> comparator = new Comparator<T>() { @Override public int compare(T O1, T O2) { T o1 = O1.基準にしたい変数名; T o2 = O2.基準にしたい変数名; Integer judgement = Integer.valueOf(o1).compareTo(Integer.valueOf(o2)); return judgement; } };
大きい順に並べたい場合は
Comparator<T> comparator = new Comparator<T>() {
@Override
public int compare(T O1, T O2) {
T o1 = O1.基準にしたい変数名;
T o2 = O2.基準にしたい変数名;
Integer judgement = Integer.valueOf(o1).compareTo(Integer.valueOf(o2));
return -judgement; //マイナスが付くかどうかだけの違い
}
};
O1とO2はArrayListの要素であるインスタンスです。
具体例
例えば、ArrayListの要素がHumanクラスのインスタンスで、そのインスタンスが持つint型の変数ageを基準にしてageが小さい順に並べ替えたい場合は次のようになります。
Comparator<Human> comparator = new Comparator<Human>() { @Override public int compare(Human O1, Human O2) { Integer o1 = O1.age; Integer o2 = O2.age; Integer judgement = Integer.valueOf(o1).compareTo(Integer.valueOf(o2)); return judgement; } };
sortメソッドにルールを教える
sortメソッドを使うときに、先ほどの「comparator」という変数を第2引数に渡します。
ollections.sort(ArrayList, comparator);
一番最初に紹介したスクリプトの49行でこれをやってます。
最後に
この方法を活用すると、ArrayListの要素にした配列を長さ順で並べ替えるなんてこともできます。
ぜひ試してみてください。
説明がわかりづらいにも関わらず、最後まで読んでくださってありがとうございました💦
コメント