121

フィールドで並べ替える必要があるオブジェクトのリストがあります。たとえば、スコアです。あまり考えずに、Comparator を実装する新しいクラスを作成しました。これはタスクを実行し、機能します。

これを振り返ってみると、Comparator を実装する新しいクラスを作成する代わりに、クラスに Comparable を実装させるべきかどうか疑問に思っています。スコアは、オブジェクトが並べられる唯一のフィールドです。

  1. 私がやったことは実践として受け入れられるでしょうか?

  2. 「最初にクラスに Comparable を実装させ (自然な順序付けのために)、別のフィールド比較が必要な場合は、Comparator を実装する新しいクラスを作成する」という正しいアプローチはありますか?

  3. 上記の(2)が当てはまる場合、クラスに Comparable を実装させた後にのみ Comparator を実装する必要があるということですか? (私が元のクラスを所有していると仮定します)。

4

19 に答える 19

135

問題のオブジェクトのデフォルトComparableの (自然な) 順序付け動作を定義する場合に使用します。これには、オブジェクトの技術的または自然な (データベース?) 識別子を使用するのが一般的です。

外部の制御可能Comparatorな順序付け動作を定義する場合に使用します。これにより、デフォルトの順序付け動作をオーバーライドできます。

于 2010-02-15T15:17:45.680 に答える
84

それがクラスをソートする明確で自然な方法である場合、オブジェクトは Comparable を実装する必要があり、クラスをソートする必要がある人は一般にそのようにしたいと思います。

ただし、並べ替えがクラスの通常とは異なる使用方法である場合、または並べ替えが特定のユース ケースでのみ意味をなす場合は、Comparator の方が適切なオプションです。

別の言い方をすれば、クラス名が与えられた場合、同等のものがどのようにソートされるかは明らかですか、それとも javadoc を読むことに頼る必要がありますか? 後者の場合、将来のすべてのソートのユースケースでコンパレータが必要になる可能性が高く、その時点で、コンパレートの実装はクラスのユーザーの速度を速めるのではなく、遅くする可能性があります。

于 2010-02-15T15:18:21.280 に答える
61

使用Comparable

  • オブジェクトがあなたのコントロールにある場合。
  • 比較動作が主な比較動作である場合。

使用Comparator

  • オブジェクトが制御不能であり、それらを実装させることができない場合Comparable
  • Comparableデフォルト(で指定される)の動作とは異なる動作を比較したい場合。
于 2010-02-15T15:21:33.057 に答える
26

同等-java.lang.Comparable: int compareTo(Object o1)

比較可能なオブジェクトは、自分自身を別のオブジェクトと比較できます。インスタンスを比較できるようにするには、クラス自体が java.lang.Comparable インターフェースを実装する必要があります。

  • 現在のオブジェクトと提供されたオブジェクトを比較できます。
  • これを使用することonly one sort sequenceで、インスタンスのプロパティに基づいて実装できます。元:Person.id
  • String、Wrapper クラス、Date、Calendar などの定義済みクラスの一部は、Comparable インターフェイスを実装しています。

コンパレータ-java.util.Comparator: int compare(Object o1, Object o2)

比較オブジェクトは、2 つの異なるオブジェクトを比較できます。クラスはそのインスタンスを比較していませんが、他のクラスのインスタンスを比較しています。このコンパレータ クラスは、java.util.Comparator インターフェースを実装する必要があります。

  • 同じタイプの任意の 2 つのオブジェクトを比較できます。
  • これを使用することmany sort sequenceで、インスタンスのプロパティに基づいて、それぞれを実装して名前を付けることができます。元:Person.id, Person.name, Person.age
  • カスタマイズされた並べ替えのために、事前定義されたクラスに Comparator インターフェイスを実装できます。

例:

public class Employee implements Comparable<Employee> {

    private int id;
    private String name;
    private int age;
    private long salary;

    // Many sort sequences can be created with different names.
    public static Comparator<Employee> NameComparator = new Comparator<Employee>() {         
        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getName().compareTo(e2.getName());
        }
    };
    public static Comparator<Employee> idComparator = new Comparator<Employee>() {       
        @Override
        public int compare(Employee e1, Employee e2) {
            return Integer.valueOf(e1.getId()).compareTo(Integer.valueOf(e2.getId()));
        }
    };

    public Employee() { }
    public Employee(int id, String name, int age, long salary){
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }
    // setters and getters.

    // Only one sort sequence can be created with in the class.
    @Override
    public int compareTo(Employee e) {
    //return Integer.valueOf(this.id).compareTo(Integer.valueOf(e.id));
    //return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0)));
        if (this.id > e.id) {
            return 1;
        }else if(this.id < e.id){
            return -1;
        }else {
            return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0)));
        }

    }   

    public static void main(String[] args) {

        Employee e1 = new Employee(5, "Yash", 22, 1000);
        Employee e2 = new Employee(8, "Tharun", 24, 25000);

        List<Employee> list = new ArrayList<Employee>();
        list.add(e1);
        list.add(e2);
        Collections.sort(list); // call @compareTo(o1)
        Collections.sort(list, Employee.nameComparator); // call @compare (o1,o2)
        Collections.sort(list, Employee.idComparator); // call @compare (o1,o2)
    }
}
  • カスタマイズされた並べ替えの場合は、コンパレータ @compare(o1, o2) を使用します。他のシナリオでは、比較可能な @compareTo(o1) を使用します。複数のフィールドを並べ替えたい場合は、コードを変更せずにコンパレータを使用します。

Java 8 Lambda : Comparatorについては、私の投稿を参照してください。

于 2015-07-06T11:24:03.410 に答える
13

同じクラスのインスタンスを比較する場合は、Comparable を使用する必要があります。

Comparator を使用して、異なるクラスのインスタンスを比較できます。

Comparable は、オブジェクトの自然順序付けを定義する必要があるクラスによって実装されます。たとえば、String は Comparable を実装します。

異なるソート順が必要な場合は、コンパレータを実装し、2 つのインスタンスを比較する独自の方法を定義します。

于 2011-07-06T08:23:46.933 に答える
10

Comparator は、Compariable が行うことすべてに加えて、さらに多くのことを行います。

| | Comparable | Comparator ._______________________________________________________________________________ Is used to allow Collections.sort to work | yes | yes Can compare multiple fields | yes | yes Lives inside the class you’re comparing and serves | | as a “default” way to compare | yes | yes Can live outside the class you’re comparing | no | yes Can have multiple instances with different method names | no | yes Input arguments can be a list of | just Object| Any type Can use enums | no | yes

次のように、コンパレータを匿名クラスとして使用する最良の方法を見つけました。

private static void sortAccountsByPriority(List<AccountRecord> accounts) {
    Collections.sort(accounts, new Comparator<AccountRecord>() {

        @Override
        public int compare(AccountRecord a1, AccountRecord a2) {
            return a1.getRank().compareTo(a2.getRank());
        }
    });
}

並べ替えを計画しているクラス内で、そのようなメソッドの複数のバージョンを作成できます。したがって、次のことができます。

  • sortAccountsByPriority
  • sortAccountsByType
  • sortAccountsByPriorityAndType

    等...

これで、これらの並べ替えメソッドをどこでも使用して、コードを再利用できます。これにより、同等のすべての機能に加えて、さらに多くの機能が得られます...したがって、同等を使用する理由はまったくありません。

于 2014-11-16T08:27:34.267 に答える
8

私はこう言います:

  • 比較が直感的である場合は、必ず Comparable を実装してください
  • 比較が直感的であるかどうかが不明な場合は、 Comparator を使用してください。より明示的であり、コードを維持しなければならない貧しい魂にとってより明確です。
  • 複数の直感的な比較が可能な場合は、比較するクラスのファクトリ メソッドによってビルドされる可能性がある Comparator を使用したいと思います。
  • 比較が特別な目的の場合は、Comparator を使用します
于 2010-02-15T15:31:03.343 に答える
7

次の点は、どの状況で Comparable を使用し、どの Comparator で使用するかを決定するのに役立ちます。

1) コードの可用性

2) 単一のソート基準と複数のソート基準

3) Arays.sort() と Collection.sort()

4) SortedMap と SortedSet のキーとして

5) より多くのクラスと柔軟性

6) クラス間比較

7) 自然秩序

より詳細な記事については、いつ比較対象を使用し、いつ比較演算子を使用するかを参照できます

于 2015-07-26T02:41:32.393 に答える
5

自然な順序の並べ替えが必要な場合-ユーザー比較可能カスタムの順序の並べ替えが必要な場合-コンパレータを使用

例:

Class Employee{
private int id;
private String name;
private String department;
}

自然な順序の並べ替えはidに基づいています。これは、一意であり、カスタムの順序の並べ替えは名前と部門であるためです。

参照:
クラスはいつComparableおよび/またはComparatorである必要がありますか? http://javarevisited.blogspot.com/2011/06/comparator-and-comparable-in-java.html

于 2011-10-12T10:02:45.317 に答える
3

ここに同様の質問がありました:クラスはいつ Comparable および/または Comparator になる必要がありますか?

私は次のように言います: 内部 ID に基づくなど、自然な順序付けのようなものに対して Comparable を実装します。

複数のフィールドなど、より複雑な比較アルゴリズムがある場合は、 Comparator を実装します。

于 2010-02-15T15:17:33.433 に答える
2

Comparable:
同種の要素のみを保存し、デフォルトの自然な並べ替え順序が必要な場合はいつでも、 comparableインターフェイスを実装するクラスに行くことができます。

Comparator:
同種の要素と異種の要素を格納し、デフォルトのカスタマイズされた並べ替え順序で並べ替えたいときはいつでも、comparatorインターフェイスを使用できます。

于 2011-12-12T03:18:47.377 に答える
0

あるインタビューで、特定の範囲の数値を nlogn 時間よりも早くソートするように求められました。(カウンティングソートは使用しません)

オブジェクトに Comparable インターフェイスを実装すると、暗黙的な並べ替えアルゴリズムで、オーバーライドされた compareTo メソッドを使用して並べ替え要素を並べ替えることができます。これは線形時間になります。

于 2015-07-15T18:30:35.987 に答える
0

クラスを所有している場合は、Comparableを使用してください。一般に、クラスを所有していない場合はComparatorが使用されますが、Comparator は TreeSet または TreeMap のコンストラクターでパラメーターとして渡すことができるため、 TreeSetまたはTreeMapで使用する必要があります。Comparator と Comparable の使用方法は、 http://preciselyconcise.com/java/collections/g_comparator.phpで確認できます。

于 2014-05-20T12:02:43.817 に答える
0

私の必要性は、日付に基づいてソートすることでした。

それで、私は Comparable を使用しましたが、それは私にとって簡単に機能しました。

public int compareTo(GoogleCalendarBean o) {
    // TODO Auto-generated method stub
    return eventdate.compareTo(o.getEventdate());
}

Comparable の制限の 1 つは、リスト以外のコレクションには使用できないことです。

于 2012-10-29T08:00:23.770 に答える
-1

非常に単純なアプローチは、問題のエンティティ クラスがデータベースで表され、データベース テーブルでエンティティ クラスのフィールドで構成されるインデックスが必要になると仮定することです。答えが「はい」の場合は、同等のものを実装し、自然な並べ替え順序のためにインデックス フィールドを使用します。それ以外の場合はすべてコンパレータを使用します。

于 2011-10-12T05:58:22.670 に答える
-2

Comparableとを実装するための私の注釈ライブラリComparator

public class Person implements Comparable<Person> {         
    private String firstName;  
    private String lastName;         
    private int age;         
    private char gentle;         

    @Override         
    @CompaProperties({ @CompaProperty(property = "lastName"),              
        @CompaProperty(property = "age",  order = Order.DSC) })           
    public int compareTo(Person person) {                 
        return Compamatic.doComparasion(this, person);         
    }  
}

リンクをクリックして、他の例を表示します。 http://code.google.com/p/compamatic/wiki/CompamaticByExamples

于 2012-01-08T01:42:31.077 に答える