Javaでコンパレータを学習しようとしていますが、この素晴らしい例をオンラインで見つけました。私の名前は、このコードをどのように変更し、最も古いものが最初で、最も若いものが最後ですか?
class Dog implements Comparator<Dog>, Comparable<Dog>{
private String name;
private int age;
Dog(){
}
Dog(String n, int a){
name = n;
age = a;
}
public String getDogName(){
return name;
}
public int getDogAge(){
return age;
}
// Overriding the compareTo method
public int compareTo(Dog d){
return (this.name).compareTo(d.name);
}
// Overriding the compare method to sort the age
public int compare(Dog d, Dog d1){
return d.age - d1.age;
}
}
public class Example{
public static void main(String args[]){
// Takes a list o Dog objects
List<Dog> list = new ArrayList<Dog>();
list.add(new Dog("Shaggy",3));
list.add(new Dog("Lacy",2));
list.add(new Dog("Roger",10));
list.add(new Dog("Tommy",4));
list.add(new Dog("Tammy",1));
Collections.sort(list);// Sorts the array list
for(Dog a: list)//printing the sorted list of names
System.out.print(a.getDogName() + ", ");
// Sorts the array list using comparator
Collections.sort(list, new Dog());
System.out.println(" ");
for(Dog a: list)//printing the sorted list of ages
System.out.print(a.getDogName() +" : "+
a.getDogAge() + ", ");
}
}
単に変化する
public int compare(Dog d, Dog d1) {
return d.age - d1.age;
}
に
public int compare(Dog d, Dog d1) {
return d1.age - d.age;
}
それがあなたが探しているものである場合、年齢の逆順でそれらをソートする必要があります。
更新:
@Arianは彼のコメントで正しいです。犬のコンパレーターを宣言する受け入れられた方法の1つは、それをクラス自体のpublic static finalフィールドとして宣言することです。
class Dog implements Comparable<Dog> {
private String name;
private int age;
public static final Comparator<Dog> DESCENDING_COMPARATOR = new Comparator<Dog>() {
// Overriding the compare method to sort the age
public int compare(Dog d, Dog d1) {
return d.age - d1.age;
}
};
Dog(String n, int a) {
name = n;
age = a;
}
public String getDogName() {
return name;
}
public int getDogAge() {
return age;
}
// Overriding the compareTo method
public int compareTo(Dog d) {
return (this.name).compareTo(d.name);
}
}
次のように、コードのどこで犬を比較したいのであれば、それを使用できます。
// Sorts the array list using comparator
Collections.sort(list, Dog.DESCENDING_COMPARATOR);
Comparableを実装するときに覚えておくべきもう1つの重要なことは、compareToがequalsで一貫して実行されることが重要であることです。必須ではありませんが、そうしないと、Setの一部の実装など、一部のコレクションで奇妙な動作が発生する可能性があります。 compareToの実装の健全な原則の詳細については、 this postを参照してください。
更新2:クリスは正しい、このコードは年齢の大きな負の値に対してオーバーフローしやすい。これをJava 7以上で実装する正しい方法は、d.age - d1.age
ではなくInteger.compare(d.age, d1.age)
になります。
更新3:Java 8を使用すると、Comparatorは次のように簡潔に記述できます。
public static final Comparator<Dog> DESCENDING_COMPARATOR =
Comparator.comparing(Dog::getDogAge).reversed();
Collections.sort
の構文は同じままですが、compare
は次のように記述できます。
public int compare(Dog d, Dog d1) {
return DESCENDING_COMPARATOR.compare(d, d1);
}
単に交換してください:
return d.age - d1.age;
沿って:
return ((Integer)d.age).compareTo(d1.age);
または、リストを逆に反転します。
return ((Integer)d1.age).compareTo(d.age);
編集:
「メモリの問題」を修正しました。
実際には、age
クラスのDog
フィールドをInteger
に変更することをお勧めします。なぜなら、null
のような多くの利点があるからです...
public class DogAgeComparator implements Comparator<Dog> {
public int compare(Dog o1, Dog o2) {
return Integer.compare(o1.getAge(), o2.getId());
}
}
Java 8から使用できます:
Comparator.comparingInt(Dog::getDogAge).reversed();
一つの簡単な方法は
Comparator<Dog> ageAscendingComp = ...;
Comparator<Dog> ageDescendingComp = Collections.reverseOrder(ageAscendingComp);
// then call the sort method
補足として、DogはComparator
を実際に実装すべきではありません。それはあなたがのような奇妙なことをしなければならないことを意味します
Collections.sort(myList, new Dog("Rex", 4));
// ^-- why is a new dog being made? What are we even sorting by?!
Collections.sort(myList, myList.get(0));
// ^-- or perhaps more confusingly
むしろ、コンパートメントを個別のクラスとして作成する必要があります。
例えば。
public class DogAgeComparator implments Comparator<Dog> {
public int compareTo(Dog d1, Dog d2) {
return d1.getAge() - d2.getAge();
}
}
これには、クラスの名前を使用してコンパレータがリストをソートする方法を示すことができるという追加の利点があります。例えば。
Collections.sort(someDogs, new DogNameComparator());
// now in name ascending order
Collections.sort(someDogs, Collections.reverseOrder(new DogAgeComparator()));
// now in age descending order
また、Comparable
をDogに実装させないでください。 Comparable
インターフェースは、これらのオブジェクトを順序付けする固有の自然な方法(数値や文字列など)があることを示すために使用されます。これはDogオブジェクトには当てはまりません。年齢でソートしたい場合もあれば、名前でソートしたい場合もあります。
Java 8 Comparable API)にアクセスできる場合、Comparable.comparingToInt()
を使用できます( Java 8 Comparable Documentation を参照)。
たとえば、年齢で降順でDog
インスタンスをソートする_Comparator<Dog>
_は、次のように作成できます。
Comparable.comparingToInt(Dog::getDogAge).reversed();
この関数は、T
からInteger
へのラムダマッピングを取得し、昇順コンパレータを作成します。連鎖関数.reversed()
は、昇順コンパレータを降順コンパレータに変換します。
注:これはAndroidのほとんどのバージョンでは役に立たないかもしれませんが、Android以外の= Javaアプリケーション。同じ場所にいる他の人にとって、自分が何に落ち着いたのかを知ることは役立つと思いました。