フィールドで並べ替える必要があるオブジェクトのリストがあります(スコアなど)。あまり考えずに、Comparatorを実装する新しいクラスを作成しました。これはタスクを実行し、機能します。
これを振り返ってみると、Comparatorを実装する新しいクラスを作成するのではなく、代わりに私のクラスにComparableを実装させる必要があるのかと思っています。スコアは、オブジェクトが注文される唯一のフィールドです。
私が実践として受け入れたことは何ですか?
適切なアプローチは、「最初にクラスにComparableを実装させ(自然順序付けのために)、代替フィールドの比較が必要な場合、Comparatorを実装する新しいクラスを作成する」ですか?
上記の(2)が真である場合、クラスにComparableを実装させた後にのみComparatorを実装する必要があるということですか? (元のクラスを所有していると仮定します)。
クラスをソートするための明確で自然な方法である場合、オブジェクトはComparableを実装する必要があり、クラスをソートする必要がある人は通常、そのようにしたいでしょう。
ただし、並べ替えがクラスの異常な使用である場合、または並べ替えが特定のユースケースにのみ意味がある場合は、Comparatorの方が適しています。
別の言い方をすれば、クラス名を指定すると、同等のものがどのようにソートされるかが明確ですか、またはjavadocを読むことに頼らなければなりませんか?後者の場合、将来のすべてのソートのユースケースでコンパレータが必要になる可能性が高く、その時点で、comparableの実装はクラスのユーザーを遅くする可能性があり、スピードを上げることはできません。
問題のオブジェクトのdefault(自然)順序付け動作を定義する場合は、 Comparable
を使用します。実際には、このためにオブジェクトの技術的または自然な(データベース?)識別子を使用します。
external controllable順序付け動作を定義する場合は、 Comparator
を使用します。これにより、デフォルトの順序付け動作をオーバーライドできます。
Comparable
を使用します。
Comparator
を使用します。
Comparable
を実装できない場合。Comparable
で指定)とは異なる動作を比較する場合。Comparable -Java.lang.Comparable: int compareTo(Object o1)
比較可能なオブジェクトは、それ自体を別のオブジェクトと比較できます。クラスをインスタンスを比較できるようにするには、クラス自体がJava.lang.Comparableインターフェースを実装する必要があります。
only one sort sequence
を実装できます。 EX:Person.id
Comparator -Java.util.Comparator: int compare(Object o1, Object o2)
コンパレータオブジェクトは、2つの異なるオブジェクトを比較できます。クラスはインスタンスを比較していませんが、他のクラスのインスタンスを比較しています。このコンパレータクラスは、Java.util.Comparatorインターフェイスを実装する必要があります。
many sort sequence
を実装し、それぞれに名前を付けることができます。 EX:Person.id, Person.name, Person.age
例:
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)
}
}
Java 8 Lambda:Comparator については、私の投稿を参照してください。
Comparatorは、同等の機能に加えて、さらに多くの機能を備えています。
| | 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());
}
});
}
並べ替えを計画しているクラス内で、このようなメソッドの複数のバージョンを作成できます。だからあなたは持つことができます:
sortAccountsByPriorityAndType
等...
現在、これらの並べ替えメソッドはどこでも使用でき、コードを再利用できます。これにより、同等のものに加えて、さらに多くのものが得られます。したがって、同等のものを使用する理由はまったくありません。
同じクラスのインスタンスを比較する場合は、Comparableを使用する必要があります。
コンパレータを使用して、異なるクラスのインスタンスを比較できます。
Comparableは、オブジェクトの自然な順序を定義する必要があるクラスによって実装されます。 StringのようにComparableを実装します。
別の並べ替え順序が必要な場合は、コンパレータを実装し、2つのインスタンスを比較する独自の方法を定義できます。
私は言うだろう:
オブジェクトの並べ替えを自然な順序に基づいて行う必要がある場合はComparableを使用しますが、異なるオブジェクトの属性に対して並べ替えを行う必要がある場合は、JavaのComparatorを使用します。
ComparableとComparatorの主な違い:
+------------------------------------------------------------------------------------+
¦ Comparable ¦ Comparator ¦
¦-----------------------------------------+------------------------------------------¦
¦ Java.lang.Comparable ¦ Java.util.Comparator ¦
¦-----------------------------------------+------------------------------------------¦
¦ int objOne.compareTo(objTwo) ¦ int compareTo(objOne, objTwo) ¦
¦-----------------------------------------+------------------------------------------¦
¦ Negative, if objOne < objTwo ¦ Same as Comparable ¦
¦ Zero, if objOne == objTwo ¦ ¦
¦ Positive, if objOne > objTwo ¦ ¦
¦-----------------------------------------+------------------------------------------¦
¦ You must modify the clas whose ¦ You build a class separate from to sort. ¦
¦ instances you want to sort. ¦ the class whose instances you want ¦
¦-----------------------------------------+------------------------------------------¦
¦ Only one sort sequemce can be created ¦ Many sort sequences can be created ¦
¦-----------------------------------------+------------------------------------------¦
¦ Implemented frequently in the API by: ¦ Meant to be implemented to sort ¦
¦ String, Wrapper classes, Date, Calandar ¦ instances of third-party classes. ¦
+------------------------------------------------------------------------------------+
以下のポイントは、Comparableを使用する状況と、Comparatorを決定する際に役立ちます。
1)コードの可用性
2)単一のソート基準と複数のソート基準
3)Arays.sort()およびCollection.sort()
4)SortedMapおよびSortedSetのキーとして
5)クラス数の増加と柔軟性
6)クラス間比較
7)自然秩序
詳細な記事については、 比較可能なものを使用する場合と比較器を使用する場合 を参照してください。
自然な順序の並べ替えが必要な場合-カスタムの並べ替えが必要な場合はUser Comparable-Use Comparator
例:
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
同様の質問がここにありました: クラスが比較可能および/または比較器である必要がありますか?
私は次のように言います:自然な順序のようなもののためにComparableを実装します内部IDに基づいて
より複雑な比較アルゴリズムがある場合は、コンパレータを実装します。複数のフィールドなど。
比較可能:
同種の要素とデフォルトの自然な並べ替え順序のみを保存する場合は、comparable
インターフェイスを実装するクラスを選択できます。
コンパレータ:
同種および異種の要素を保存し、デフォルトのカスタマイズされた並べ替え順序で並べ替える場合は、comparator
インターフェイスを使用できます。
私のニーズは日付に基づいてソートされました。
そのため、Comparableを使用しましたが、簡単に機能しました。
public int compareTo(GoogleCalendarBean o) {
// TODO Auto-generated method stub
return eventdate.compareTo(o.getEventdate());
}
Comparableの制限の1つは、リスト以外のコレクションには使用できないことです。
比較可能は、数値が昇順で、文字列がアルファベット順である場合に提供されるデフォルトの自然なソート順です。例えば:
Treeset t=new Treeset();
t.add(2);
t.add(1);
System.out.println(t);//[1,2]
Comparatorは、たとえば次のような比較メソッドをオーバーライドすることにより、カスタムmyComparatorクラスに実装されたカスタムソート順です。
Treeset t=new Treeset(new myComparator());
t.add(55);
t.add(56);
class myComparator implements Comparator{
public int compare(Object o1,Object o2){
//Descending Logic
}
}
System.out.println(t);//[56,55]
クラスを所有している場合は、Comparableを使用することをお勧めします。通常、Comparatorは、クラスを所有していないが使用する必要がある場合に使用されますTreeSetまたはTreeMap。これは、ComparatorをTreeSetまたはTreeMapのコンストラクターのパラメーターとして渡すことができるためです。 ComparatorとComparableの使用方法は http://preciselyconcise.com/Java/collections/g_comparator.php で確認できます。
インタビューの1つで、nlogn時間よりも明確な範囲の数値のソートを依頼されました。 (カウントソートを使用しない)
Comparableインターフェイスをオブジェクトに実装すると、暗黙的な並べ替えアルゴリズムでオーバーライドされたcompareToメソッドを使用して要素を並べ替えることができます。これは線形時間になります。