48

私は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() + ", ");
}
}
4

6 に答える 6

102

単純に変化する

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 が equal と一貫して実行されることが重要であるということです。必須ではありませんが、そうしないと、セットの一部の実装など、一部のコレクションで奇妙な動作が発生する可能性があります。compareTo を実装するための健全な原則の詳細については、この投稿を参照してください。

更新 2: Chris の言う通りです。このコードは age の負の値が大きいとオーバーフローの影響を受けやすくなります。Java 7 以降でこれを実装する正しい方法はInteger.compare(d.age, d1.age)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);
}
于 2012-05-22T20:42:27.303 に答える
28
public class DogAgeComparator implements Comparator<Dog> {
    public int compare(Dog o1, Dog o2) {
        return Integer.compare(o1.getAge(), o2.getId());
    }
}
于 2015-05-13T07:49:31.030 に答える
21

置き換えるだけです:

return d.age - d1.age;

に:

return ((Integer)d.age).compareTo(d1.age);

または反転してリストを逆にします。

return ((Integer)d1.age).compareTo(d.age);

編集:

「メモリの問題」を修正しました。
確かに、より良い解決策は、クラスのageフィールドを に変更することです。可能性などの多くの利点があるためです...DogIntegernull

于 2012-05-22T20:43:30.357 に答える
4

1つの簡単な方法は

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

むしろ、Compartors を個別のクラスとして作成する必要があります。

例えば。

public class DogAgeComparator implments Comparator<Dog> {
    public int compareTo(Dog d1, Dog d2) {
        return d1.getAge() - d2.getAge();
    }
}

これには、クラスの名前を使用して Comparator がリストをソートする方法を指定できるという追加の利点があります。例えば。

Collections.sort(someDogs, new DogNameComparator());
// now in name ascending order

Collections.sort(someDogs, Collections.reverseOrder(new DogAgeComparator()));
// now in age descending order

また、 Dog を実装しないでくださいComparable。インターフェースは、Comparableこれらのオブジェクト (数値や文字列など) を順序付ける固有の自然な方法があることを示すために使用されます。これは Dog オブジェクトには当てはまりません。年齢で並べ替えたい場合もあれば、名前で並べ替えたい場合もあります。

于 2012-05-22T21:03:25.827 に答える
2

Java 8 Comparable API にアクセスできる場合は、役立つ可能Comparable.comparingToInt()性があります。( Java 8 の同等のドキュメントを参照してください)。

たとえば、インスタンスを年齢の降順でComparator<Dog>並べ替えるDogには、次のように作成できます。

Comparable.comparingToInt(Dog::getDogAge).reversed();

この関数は へのラムダ マッピングTを取得しInteger、昇順のコンパレータを作成します。連鎖関数.reversed()は、昇順コンパレータを降順コンパレータに変えます。

注: これはほとんどのバージョンの Android では役に立たないかもしれませんが、Android 以外の Java アプリケーションについて同様の情報を検索しているときに、この質問に出会いました。私が最終的に何に落ち着いたかを見ることは、同じ場所にいる他の人にとって役立つかもしれないと思いました.

于 2016-08-15T23:24:07.210 に答える