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

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 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) in the type Collections
  is not applicable for the arguments (ArrayList)

ここで何が悪かったのか理解しましょう。

3. Comparable

名前が示すように、Comparable is an interface defining a strategy of comparing an object with other objects of the same type. This is called the class’s “natural ordering”.

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

public class Player implements Comparable {

    //...
    @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を使用した自然な順序付けについて明確に理解できたので、インターフェイスを直接実装するのではなく、how we can use other types of ordering, in a more flexible mannerを見てみましょう。

4. Comparator

比較されたオブジェクトを表し、Comparable.compareTo()メソッドと同様に機能する2つの引数を持つThe Comparator interface defines a compare(arg1, arg2) method

4.1. Comparatorsの作成

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

最初の例では、Comparatorを作成して、Playerranking属性を使用してプレーヤーを並べ替えます。

public class PlayerRankingComparator implements Comparator {

    @Override
    public int compare(Player firstPlayer, Player secondPlayer) {
       return (firstPlayer.getRanking() - secondPlayer.getRanking());
    }
}

同様に、Comparatorを作成して、Playerage属性を使用してプレーヤーを並べ替えることができます。

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

4.2. Comparatorsの動作

概念を示すために、実際に使用するComparatorのインスタンスであるCollections.sort methodに2番目の引数を導入して、PlayerSorterを変更してみましょう。

Using this approach, we can override the natural ordering

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

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

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 8Comparators

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

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

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

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

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

Java 8 Comparator.comparingガイドでJava8の機能を詳しく調べることができます。

5. ComparatorComparable

The Comparable interface is a good choice when used for defining the default ordering、つまり、オブジェクトを比較する主な方法である場合。

次に、すでにComparableがあるのに、なぜComparatorを使用するのかを自問する必要があります。

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

  • オブジェクトを並べ替えるクラスのソースコードを変更できないため、Comparableを使用できない場合があります。

  • Comparatorsを使用すると、ドメインクラスにコードを追加する必要がなくなります。

  • Comparableを使用する場合には不可能な、複数の異なる比較戦略を定義できます。

6. 結論

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

並べ替えのより高度なトピックを理解するには、Java 8 ComparatorJava 8 Comparison with Lambdasなどの他の記事を確認してください。

そして、いつものように、ソースコードはover on Githubで見つけることができます。