HOWTO · Java

Java でコンパレータをソート

この記事では、Java のソートコンパレータとその使用方法を紹介します。

このページの内容

この記事では、Java のソート・コンパレーターとは何かを定義し、それをプロセスで使用する方法を示します。この概念をよりよく理解するのに役立つ、従うことができるプログラムが含まれています。

Java で DepartmentComparator を使用して要素を並べ替える

ソートは、リスト配列のようなデータ構造を明確な順序で配置するプロセスです。このプロセスは、データ要素を比較することで機能するため、新しい位置を定義します。Java で定義されているソートアルゴリズムには、構造の複雑さに基づいて役立つさまざまなタイプがあります。

以下は、要素をソートするための実装を提供するためにコンパレータインターフェイスをオーバーライドすることを定義するコードブロックです。

import java.util.*;

public class DepartmentComparator {
  public static void main(String[] args) {
    List<Department> departments = Arrays.asList(new Department("dept1", 2001),
        new Department("dept2", 1998), new Department("dept3", 2021));
    Collections.sort(departments, new LexicographicComparator());
    System.out.println("Sorting on the basis of name: " + departments);
    Collections.sort(departments, new YearComparator());
    System.out.println("Sorting on the basis of year: " + departments);
  }

  static class LexicographicComparator implements Comparator<Department> {
    @Override
    public int compare(Department a, Department b) {
      return a.name.compareToIgnoreCase(b.name);
    }
  }

  static class YearComparator implements Comparator<Department> {
    @Override
    public int compare(Department a, Department b) {
      return a.establish_year < b.establish_year ? -1
          : a.establish_year == b.establish_year ? 0
                                                 : 1;
    }
  }

  static class Department {
    String name;
    int establish_year;

    Department(String n, int a) {
      name = n;
      establish_year = a;
    }

    @Override
    public String toString() {
      return String.format("{name=%s, Establish Year=%d}", name, establish_year);
    }
  }
}

上記のプログラムでは、DepartmentComparator クラスは main メソッドを保持し、ドライバーコードとして機能するパブリッククラスです。メインクラス以外に、コードには機能を示すために追加された非公開クラスがあります。Department クラスは、フィールド名と establish_year 変数を保持し、toString() 関数をオーバーライドする POJO です。Bean クラスとは別に、LexicographicComparator クラスと YearComparator クラスは Comparator インターフェイスを実装します。

静的メソッドでは、リストは 3つの要素で初期化されます。Array.asList は、固定サイズの List を返す静的メソッドです。この関数は、クラスのインスタンスを取得してリストに変換します。そのため、department class インスタンスは新しいキーワードを使用して作成され、parameterized コンストラクターと呼ばれるようになりました。このコンストラクターは名前を初期化し、渡されたパラメーターから年を確立します。

リストが作成されると、Collections クラスの sort メソッドが呼び出されます。指定されたコンパレータに基づいて、定義されたリストまたはコレクションをソートします。このメソッドは手動コンパレータを取り、void を返しますが、引数として渡されたコレクションを変更します。要素が異なるタイプの場合、メソッドは ClassCastException をスローします。このメソッドは、最初の引数としてリストコレクションを取り、2 番目の引数として手動コンパレータを取ります。

LexicographicComparator クラスと YearComparator クラスは、手動で比較するために作成されます。クラスは、比較に基づいて int 値を返す単一のメソッド compare を備えた Comparator である機能インターフェイスを実装します。メソッドは、ユーザー指定の実装を定義できるユーザー定義クラスでオーバーライドされます。

LexicographicComparator クラスでは、メソッドは名前に基づいて条件を指定し、渡された引数を比較し、入力が小さいか大きいか等しいかに基づいて -1、0、または 1 を返します。お互いに。同様に、YearComparator メソッドは、引数として渡された年を比較するためにオーバーライドされます。

以下は、名前、昇順、年ごとに並べられた出力です。

Sorting on the basis of name: [{name=dept1, Establish Year=2001}, {name=dept2, Establish Year=1998}, {name=dept3, Establish Year=2021}]
Sorting on the basis of year: [{name=dept2, Establish Year=1998}, {name=dept1, Establish Year=2001}, {name=dept3, Establish Year=2021}]

Java 8 の lambda 関数を使用して上記のプログラムを変更する

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class DepartmentCompareUsingJava8 {
  public static void main(String[] args) {
    List<DepartmentComparator.Department> departments =
        Arrays.asList(new DepartmentComparator.Department("dept1", 2001),
            new DepartmentComparator.Department("dept2", 1998),
            new DepartmentComparator.Department("dept3", 2021));
    Collections.sort(departments, (a, b) -> a.name.compareToIgnoreCase(b.name));
    System.out.println(departments);
    Collections.sort(departments,
        (a, b)
            -> a.establish_year < b.establish_year ? -1
            : a.establish_year == b.establish_year ? 0
                                                   : 1);
    System.out.println(departments);
  }
}

このプログラムの違いは、Comparator インターフェースを実装する新しいクラスを定義する代わりに、Java 8 関数型インターフェースが毎回新しいクラスでの処理のオーバーヘッドを削減するのに役立つことです。Functional Interface には、実装されていないメソッドまたは abstract メソッドが 1つあります。インターフェイスを実装し、独自のメソッドバージョンを提供するクラスを作成するオーバーヘッドを削減します。

ラムダ ()-> 関数を使用して、メソッドを直接呼び出します。ラムダは関数を引数として扱い、インスタンス化にクラスを必要としません。この関数はパラメーターを受け取り、別のクラスではなく同じ行に実装を提供します。

上記のプログラムの出力は、最初のコードの出力と同じです。