【Java】ArrayListの要素になってるインスタンスをソートする

未分類
Michael Schwarzenberger on Pixabay

こんにちは、コンスキです。

インスタンスを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の要素にした配列を長さ順で並べ替えるなんてこともできます。

ぜひ試してみてください。

説明がわかりづらいにも関わらず、最後まで読んでくださってありがとうございました💦

コメント

タイトルとURLをコピーしました