コンパレータとJavaでの比較可能

1前書き

Javaでの比較は非常に簡単です - そうでない限り。

カスタムタイプを使用したり、直接比較できないオブジェクトを比較しようとするときは、比較戦略を使用する必要があります。単純に構築できますが、 Comparator または Comparable インターフェースを利用します。

2例の設定

フットボールチームの例を見てみましょう。ここでは、選手たちをランキング順に並べます。

単純な Player クラスを作成することから始めます。

public class Player {
    private int ranking;
    private String name;
    private int age;

   //constructor, getters, setters
}

次に、コレクションを作成するための PlayerSorter クラスを作成し、それを Collections.sort を使用して並べ替えます

public static void main(String[]args) {
    List<Player> footballTeam = new ArrayList<>();
    Player player1 = new Player(59, "John", 20);
    Player player2 = new Player(67, "Roger", 22);
    Player player3 = new Player(45, "Steven", 24);
    footballTeam.add(player1);
    footballTeam.add(player2);
    footballTeam.add(player3);

    System.out.println("Before Sorting : " + footballTeam);
    Collections.sort(footballTeam);
    System.out.println("After Sorting : " + footballTeam);
}

ここで、予想通り、これはコンパイル時エラーになります。

The method sort(List<T>) in the type Collections
  is not applicable for the arguments (ArrayList<Player>)

ここで私たちが間違ったことを理解しましょう。

3 同程度の

名前が示すように、 Compaparable は、オブジェクトを同じタイプの他のオブジェクトと比較する方法を定義するインタフェースです。これはクラスの「自然順序付け」と呼ばれます。

したがって、ソートできるようにするには、 Comparable インターフェースを実装して、 Player オブジェクトを比較可能として定義する必要があります。

public class Player implements Comparable<Player> {

   //...
    @Override
    public int compareTo(Player otherPlayer) {
        return (this.getRanking() - otherPlayer.getRanking());
    }
}
  • ソート順は compareTo() メソッドの戻り値によって決まります。

このメソッドは、比較されているオブジェクトが引数として渡されているオブジェクトよりも小さい、等しい、または大きいかどうかを示す数値を返します。

最後に、 PlayerSorter を今実行すると、 Players がランキング順に表示されます。

Before Sorting :[John, Roger, Steven]After Sorting :[Steven, John, Roger]----

__Comparable__を使用して自然順序付けを明確に理解できたので、次に、インターフェイスを直接実装するよりも、** 柔軟な方法で** 他の種類の順序付けを使用する方法を見てみましょう。

===  **  4 __コンパレータ__**

**  __Comparator__インターフェースは、比較されるオブジェクトを表す2つの引数を持つ__compare(arg1、arg2)__メソッドを定義し、__Comparable.compareTo()メソッドと同様に機能します。

====  **  4.1.  __Comparators__ ** を作成する

__Comparatorを作成するには、__Comparator__インターフェースを実装する必要があります。

最初の例では、プレイヤーをソートするために__Player__の__ranking__属性を使用するための__Comparator__を作成します。

[source,java,gutter:,true]

public class PlayerRankingComparator implements Comparator<Player> {

    @Override
    public int compare(Player firstPlayer, Player secondPlayer) {
       return (firstPlayer.getRanking() - secondPlayer.getRanking());
    }
}
同様に、__Player__の__age__属性を使用してプレーヤーをソートするための__Comparator__を作成できます。

[source,java,gutter:,true]

public class PlayerAgeComparator implements Comparator<Player> { @Override public int compare(Player firstPlayer, Player secondPlayer) { return (firstPlayer.getAge() - secondPlayer.getAge()); } }

====  **  4.2. アクションの__比較__

概念を説明するために、__Collections.sortメソッドに2番目の引数を導入して__PlayerSorter__を変更します。これは実際には使用する__Comparator__のインスタンスです。

** このアプローチを使うと、自然な順序を上書きすることができます** :

[source,java,gutter:,true]

PlayerRankingComparator playerComparator = new PlayerRankingComparator(); Collections.sort(footballTeam, playerComparator);

それでは、__PlayerRankingSorterを実行して結果を確認しましょう。

[source,java,gutter:,true]

Before Sorting :[John, Roger, Steven]After Sorting by ranking :[Steven, John, Roger]----

別のソート順が必要な場合は、使用している Comparator を変更するだけです。

PlayerAgeComparator playerComparator = new PlayerAgeComparator();
Collections.sort(footballTeam, playerComparator);

さて、 PlayerAgeSorter を実行すると、__ageによって異なるソート順を見ることができます。

Before Sorting :[John, Roger, Steven]After Sorting by age :[Roger, John, Steven]----

====  **  4.3.  Java 8 __コンパレーター__ **

Java 8は、ラムダ式と__comparing()__静的ファクトリメソッドを使用して__Comparators__を定義する新しい方法を提供します。

ラムダ式を使用して__Comparator__を作成する方法の簡単な例を見てみましょう。

[source,java,gutter:,true]

Comparator<Player> byRanking = (Player player1, Player player2) → player1.getRanking() - player2.getRanking();

__Comparator.comparing__メソッドは、アイテムの比較に使用されるプロパティを計算するメソッドを受け取り、一致する__Comparator__インスタンスを返します。

[source,java,gutter:,true]

Comparator<Player> byRanking = Comparator .comparing(Player::getRanking); Comparator<Player> byAge = Comparator .comparing(Player::getAge);

あなたは私たちのリンクでJava 8の機能性を深く探ることができます:/java-8-コンパレータ - 比較[Java 8 Comparator.comparing]ガイド

===  **  __ 5. コンパレータ__比較__比較可能**

**  __Comparable__インターフェースは、デフォルトの順序を定義するために使用される場合、または言い換えれば、それがオブジェクトを比較する主な方法である場合に適しています。

それでは、私たちがすでに__比較可能__を持っているのなら、なぜ__比較__を使うのかと自問しなければなりません。

いくつかの理由があります:

** 場合によっては、オブジェクトを含むクラスのソースコードを変更できないことがあります。

ソートしたいので、__比較__を使用できません
**  __Comparators__を使うことで、コードを追加することを避けることができます。

ドメインクラス
** 複数の異なる比較戦略を定義することはできませんが、

__Comparable__を使うと可能
**

===  **  6. 結論**

このチュートリアルでは、__Comparable__と__Comparator__インターフェイスを調べ、それらの違いについて説明しました。

ソートのより高度なトピックを理解するには、link:/java-8-compiler-比べ[Java 8 Comparator]、link:/java-8-sort-lambda[Java 8 Lambdasとの比較]などの他の記事を調べてください。

そして、いつもどおり、ソースコードはhttps://github.com/eugenp/tutorials/tree/master/core-java-lang[over on Github]にあります。