compare()とcompareTo()の違いは何ですか?


110

Java compare()compareTo()メソッドの違いは何ですか?それらの方法は同じ答えを出しますか?


1
どのクラスメソッドを比較するのですか?
Markus Lausberg、

compare()とcompareTo()の両方の使用に関する詳細な説明については、sysdotoutdotprint.com
2017/03/28

回答:


160

JavaNotesから:

  • a.compareTo(b)
    比較可能なインターフェース:値を比較し、値がより小さいか、等しいか、より大きいかを示す整数を返します。
    クラスオブジェクトに自然な順序がある場合は、Comparable<T>インターフェースを実装し、このメソッドを定義します。自然順序付けの実装を持つすべてのJavaクラスComparable<T>-例:StringラッパークラスBigInteger

  • compare(a, b)
    コンパレータインターフェイス: 2つのオブジェクトの値を比較します。これは、の一部として実装されるComparator<T>インタフェース、及び典型的な使用は、次のようなメソッドに渡すこれを実現する一つまたはそれ以上の小さなユーティリティクラスを定義することであるsort()か、などのデータ構造をソートすることによって使用するためにTreeMap及びTreeSet。以下のComparatorオブジェクトを作成できます。

    • 複数の比較。何かをソートするいくつかの異なる方法を提供するため。たとえば、Personクラスを名前、ID、年齢、高さなどで並べ替えることができますsort()。メソッドに渡すこれらのそれぞれに対してコンパレータを定義します。
    • システムクラス制御できないクラスの比較メソッドを提供します。たとえば、長さで比較する文字列のコンパレータを定義できます。
    • ストラテジーパターンストラテジーパターンを実装するには、パラメーターとして渡すことができるオブジェクトとしてアルゴリズムを表現したり、データ構造に保存したりする必要がある状況です。

クラスオブジェクトに1つの自然なソート順がある場合、compare()は必要ない場合があります。


http://www.digizol.com/2008/07/java-sorting-comparator-vs-comparable.htmlからの要約

比較可能比較
可能オブジェクトは、それ自体を別のオブジェクトと比較できます。

コンパレータ
コンパレータオブジェクトは、2つの異なるオブジェクトを比較できます。クラスはインスタンスを比較していませんが、他のクラスのインスタンスを比較しています。


ユースケースのコンテキスト:

同等のインターフェース

equalsメソッドと==and != 演算子は、等価/ 等価をテストしますが、相対値をテストする方法は提供しません
一部のクラス(たとえば、文字列や自然順序付けを持つ他のクラス)Comparable<T>は、compareTo()メソッドを定義するインターフェースを実装しています。またはメソッドで使用する場合は、クラス
に実装Comparable<T>するCollections.sort()必要がありArrays.sort()ます。

Comparatorオブジェクトの定義

コンパレータを作成して、任意のクラスの任意の方法で並べ替えることができます。
たとえば、StringクラスはCASE_INSENSITIVE_ORDERコンパレーターを定義します。


:二つのアプローチの違いは、の概念にリンクすることができ
順序付きコレクション

コレクションが順序付けられると、特定の(ランダムでHashtableはない)順序でコレクションを反復処理できることを意味します(a は順序付けされません)。

自然な順序のコレクションは、順序付けされるだけでなく、並べ替えられます。自然な順序の定義は難しい場合があります!自然な文字列順のように)。


コメントでHaveAGuessが指摘した別の違い:

  • Comparable は実装内にあり、インターフェースからは見えないため、並べ替えを行うと、何が起こるか本当にわかりません。
  • Comparator 順序が適切に定義されることを保証します。

2
この答えは網羅的であるため、ここに追加したいComparableについての不快な点があります。これは実装内にあり、インターフェースからは見えないため、ソートすると、何が起こるか本当にわかりません。コンパレータを使用すると、順序が適切に定義されていることを
確信

@HaveAGuess良い​​点。見やすくするために、回答にコメントを含めました。
VonC、2015年

オブジェクトには自然順序がありますが、ここで自然順序とはどういう意味ですか?たとえば従業員クラスの名前の文字列データメンバーは自然な順序ですか?
Narendra Jaggi

@NarendraJaggi en.wikipedia.org/wiki/Enumerationを参照してください。列挙を容易にする順序。インデックスセットの特定の適切な順序付けが、部分的な列挙を与えられた次の要素をリストするユニークな方法を提供するという意味での「ナチュラル」
VonC

2
@VedantKekanありがとうございます。この回答で2つのリンクを復元しました。
VonC、2016年

16

compareTo()Comparableインターフェースからです。

compare()Comparatorインターフェースからです。

どちらの方法も同じことを行いますが、各インターフェースは少し異なるコンテキストで使用されます。

同等のインターフェースを実装するクラスのオブジェクトの自然順序付けを課すために使用されます。このcompareTo()方法は自然比較法と呼ばれます。コンパレータインターフェースを実装するクラスのオブジェクトに全体順序付けを課すために使用されます。詳細については、各インターフェイスをいつ使用するかについてのリンクを参照してください。


いくつかの例を挙げられますか?どちらの方法でも同じ答えが得られますか?

「比較可能」が自然順序付けである理由がわかりませんか?カスタマイズできますか?
c-an

14

類似点:
どちらも2つのオブジェクトを比較するカスタム方法です。
どちらもint、2つのオブジェクト間の関係を説明する記述を返します。

相違点: メソッドcompare()は、Comparatorインターフェースを実装する場合に実装する義務があるメソッドです。2つのオブジェクトをメソッドに渡すことができ、intそれらの関係を説明するものを返します。

Comparator comp = new MyComparator();
int result = comp.compare(object1, object2);

メソッドcompareTo()は、Comparableインターフェースを実装する場合に実装する義務があるメソッドです。これにより、オブジェクトを類似したタイプのオブジェクトと比較できます。

String s = "hi";
int result = s.compareTo("bye");

概要:
基本的に、これらは物事を比較する2つの異なる方法です。


9

メソッドは同じ答えを与える必要はありません。それは、呼び出すオブジェクト/クラスによって異なります。

ある段階で比較することがわかっている独自のクラスを実装している場合は、それらにComparableインターフェースを実装させ、それに応じてcompareTo()メソッドを実装させることができます。

Comparableインターフェースを実装しないAPIのクラスを使用しているが、それらを比較したい場合。つまり、並べ替え。Comparatorインターフェースを実装する独自のクラスを作成し、compare()メソッドでロジックを実装できます。


3

比較可能なインターフェイスには、compareTo(obj)引数を1つだけ取り、それ自体を同じクラスの別のインスタンスまたはオブジェクトと比較する、呼び出されるメソッドが含まれています。

コンパレータインターフェイスには、compare(obj1,obj2)2つの引数を取り、同じクラスまたは異なるクラスの2つのオブジェクトの値を比較するというメソッドが含まれています。


3
compareTo(T object)

このオブジェクトを別のオブジェクトと比較して、このオブジェクトの負のint値がより小さい、0が等しい、または正の値が他方より大きいことを示すために実装されたjava.lang.Comparableインターフェースから来ます。これはより便利な比較メソッドですが、比較するすべてのクラスに実装する必要があります。

compare(T obj1, T obj2)

別のクラスのオブジェクトを比較する別のクラスに実装されているjava.util.Comparatorインターフェースから来て、最初のオブジェクトの負のint値がより小さい、0が等しい、または正の値が2番目のオブジェクトより大きい。クラスは変更できないため、compareTo()を実装できない場合に必要です。また、オブジェクトを比較する方法を1つだけではなく(名前や年齢などで)比較する場合にも使用されます。


3

コンパレータを使用すると、クラスに対してn個の比較ロジックを作成できます。

例えば

車のクラスの場合

車の型番に基づいて比較するComparatorクラスを持つことができます。車の年式に基づいて比較するためのコンパレータクラスを使用することもできます。

車のクラス

public class Car  {

    int modelNo;

    int modelYear;

    public int getModelNo() {
        return modelNo;
    }

    public void setModelNo(int modelNo) {
        this.modelNo = modelNo;
    }

    public int getModelYear() {
        return modelYear;
    }

    public void setModelYear(int modelYear) {
        this.modelYear = modelYear;
    }

}

モデル番号に基づくコンパレータ#1

public class CarModelNoCompartor implements Comparator<Car>{

    public int compare(Car o1, Car o2) {

        return o1.getModelNo() - o2.getModelNo();
    }

}

モデルイヤーに基づくコンパレータ#2

public class CarModelYearComparator implements Comparator<Car> {

    public int compare(Car o1, Car o2) {

        return o1.getModelYear() - o2.getModelYear();
    }

}

しかし、これはComparableインターフェースの場合には不可能です。

Comparableインターフェースの場合、compareTo()メソッドで使用できるロジックは1つだけです。


2

このメソッドを持つオブジェクトとその共同編集者の関係は異なります。

compareTo()はインタフェースComparableのメソッドので、このインスタンスを別のインスタンスと比較するために使用されます。

compare()はインターフェースComparatorのメソッドであるため、別のクラスの2つの異なるインスタンスを互いに比較するために使用されます。

もしそうなら、実装Comparableとはクラスのインスタンスを簡単に比較できることを意味します。
実装Comparatorとは、インスタンスが(他のクラスの)異なるオブジェクトを比較するのに適していることを意味します。


2

主な違いは、インターフェースの使用です。

Comparable(compareTo()を使用)では、オブジェクトを比較して(TreeMapを使用するため、またはリストをソートするために)、そのインターフェースを実装する必要があります。しかし、クラスがComparableを実装せず、サードパーティライブラリの一部であるため変更できない場合はどうなりますか?次に、コンパレータを実装する必要があります。これは、使用するのに少し不便です。


2

compareTo()あるオブジェクトで呼び出され、別のオブジェクトと比較されます。 compare()他の2つのオブジェクトを比較するために、いくつかのオブジェクトで呼び出されます。

違いは、実際の比較を行うロジックが定義されているところです。


私が素晴らしい答えと呼ぶものではありませんが、それは反対票に値するとは思いません。
ポールトンブリン

同意します、個人的に私は間違ったまたは誤解を招く答えのために反対票を予約します。これは間違いなく正しいです。
Joachim Sauer、

では、私に反対票を投じた「友好的な」人々はどこにいるのでしょうか?これは、誰かがポイントを逃したために反対票を投じられた私の2番目の正解です。反対投票のポイントまたは私の答えのポイントのどちらか。人生はとても残酷です
.-

0

オブジェクトFooを含むリストをソートする場合、リストのソートメソッドがこのメソッドを使用しているため、FooクラスはComparableインターフェースを実装する必要があります。

他の2つのクラスを比較するUtilクラスを作成する場合は、Comparatorクラスを実装できます。


0

従業員テーブル
名、DoB、給与
トーマス、1982年2月10日、
ダニエル300、1990年3 月11日、
クワメ400 、1998年2月10日、520

匹敵例えば、あなたが名前または給料で並べ替えることができ-インタフェースを使用すると、1つのプライマリフィールドを参照して、オブジェクト例えば従業員のリストをソートすることを可能にするのCompareTo()メソッド

emp1.getName().compareTo(emp2.getName())

そのような要件のためのより柔軟なインターフェースがComparatorインターフェースによって提供され、その唯一のメソッドはcompare()です。

public interface Comparator<Employee> {
 int compare(Employee obj1, Employee obj2);
}

サンプルコード

public class NameComparator implements Comparator<Employee> {

public int compare(Employee e1, Employee e2) {
     // some conditions here
        return e1.getName().compareTo(e2.getName()); // returns 1 since (T)omas > (D)an 
    return e1.getSalary().compareTo(e2.getSalary()); // returns -1 since 400 > 300
}

}


0

もう一つのポイント:

  • compareTo()Comparableインターフェースからのものであり、インターフェースcompare()からのものComparatorです。
  • Comparableは、クラス内のオブジェクトのデフォルトの順序Comparatorを定義するために使用され、メソッドに渡されるカスタムの順序を定義するために使用されます。

0

強調すべき技術的な側面もあります。クライアントクラスからの比較動作のパラメーター化が必要であり、次のようなメソッドを使用するのComparableComparator、それとも使用するのか疑問に思っているとします。

class Pokemon {
    int healthPoints;
    int attackDamage;
    public void battle (Comparable<Pokemon> comparable, Pokemon opponent) {
        if (comparable.compareTo(opponent) > 0) { //comparable needs to, but cannot, access this.healthPoints for example
            System.out.println("battle won");
        } else {
            System.out.println("battle lost");
        }
    }
}

comparableラムダまたはオブジェクトでありcomparablethisポケモンのフィールドにアクセスする方法はありません。(ラムダでthisは、プログラムテキストで定義されているように、ラムダのスコープ内の外部クラスインスタンスを指します。)したがって、これは飛行せずComparator、2つの引数を持つを使用する必要があります。


0

比較可能なインターフェイスを使用して、age、name、dept_nameなどの複数の値に基づいてソートします... 1つの値については、Comparatorインターフェイスを使用します


-2
Important Answar
String name;
int roll;

public int compare(Object obj1,Object obj2) { // For Comparator interface
    return obj1.compareTo(obj1);
}

public int compareTo(Object obj1) { // For Comparable Interface
    return obj1.compareTo(obj);
}

ここでreturn obj1.compareTo(obj1)or return obj1.compareTo(obj)ステートメントはObjectのみを受け取ります。プリミティブは許可されていません。例えば

name.compareTo(obj1.getName()) // Correct Statement.

だが

roll.compareTo(obj1.getRoll()) 
// Wrong Statement Compile Time Error Because roll 
// is not an Object Type, it is primitive type.

名前は文字列オブジェクトなので、機能しました。学生のロール番号をソートする場合は、以下のコードを使用してください。

public int compareTo(Object obj1) { // For Comparable Interface
    Student s = (Student) obj1;
    return rollno - s.getRollno();
}  

または

public int compare(Object obj1,Object obj2) { // For Comparator interface
    Student s1 = (Student) obj1;
    Student s2 = (Student) obj2;
    return s1.getRollno() - s2.getRollno();
}  
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.