191

コンパレータの使い方を学びましたが、コンパレータに問題があります。コードにエラーがあります:

Exception in thread "main" java.lang.ClassCastException: New.People cannot be cast to java.lang.Comparable
 at java.util.Arrays.mergeSort(Unknown Source)
 at java.util.Arrays.sort(Unknown Source)
 at java.util.Collections.sort(Unknown Source)
 at New.TestPeople.main(TestPeople.java:18)

これが私のコードです:

import java.util.Comparator;

public class People implements Comparator {
   private int id;
   private String info;
   private double price;

   public People(int newid, String newinfo, double newprice) {
       setid(newid);
       setinfo(newinfo);
       setprice(newprice);
   }

   public int getid() {
       return id;
   }

   public void setid(int id) {
       this.id = id;
   }

   public String getinfo() {
       return info;
   }

   public void setinfo(String info) {
       this.info = info;
   }

   public double getprice() {
       return price;
   }

   public void setprice(double price) {
       this.price = price;
   }

   public int compare(Object obj1, Object obj2) {
       Integer p1 = ((People) obj1).getid();
       Integer p2 = ((People) obj2).getid();

       if (p1 > p2) {
           return 1;
       } else if (p1 < p2){
           return -1;
       } else {
           return 0;
       }
    }
}
import java.util.ArrayList;
import java.util.Collections;

public class TestPeople {
    public static void main(String[] args) {
        ArrayList peps = new ArrayList();

        peps.add(new People(123, "M", 14.25));
        peps.add(new People(234, "M", 6.21));
        peps.add(new People(362, "F", 9.23));
        peps.add(new People(111, "M", 65.99));
        peps.add(new People(535, "F", 9.23));

        Collections.sort(peps);

        for (int i = 0; i < peps.size(); i++){
            System.out.println(peps.get(i));
        }
    }
}

比較方法でのキャストと何か関係があると思いますが、私はそれをいじっていましたが、それでも解決策を見つけることができませんでした

4

16 に答える 16

229

サンプルクラスにはいくつかの厄介な点があります。

  • それは人と呼ばれますが、priceand info(人ではなくオブジェクトの何か)があります。
  • クラスに何かの複数形の名前を付ける場合、それは複数のものの抽象化であることを示唆しています。

とにかく、これは a の使い方のデモですComparator<T>:

public class ComparatorDemo {

    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Joe", 24),
                new Person("Pete", 18),
                new Person("Chris", 21)
        );
        Collections.sort(people, new LexicographicComparator());
        System.out.println(people);
        Collections.sort(people, new AgeComparator());
        System.out.println(people);
    }
}

class LexicographicComparator implements Comparator<Person> {
    @Override
    public int compare(Person a, Person b) {
        return a.name.compareToIgnoreCase(b.name);
    }
}

class AgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person a, Person b) {
        return a.age < b.age ? -1 : a.age == b.age ? 0 : 1;
    }
}

class Person {

    String name;
    int age;

    Person(String n, int a) {
        name = n;
        age = a;
    }

    @Override
    public String toString() {
        return String.format("{name=%s, age=%d}", name, age);
    }
}

編集

同等の Java 8 デモは次のようになります。

public class ComparatorDemo {

    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Joe", 24),
                new Person("Pete", 18),
                new Person("Chris", 21)
        );
        Collections.sort(people, (a, b) -> a.name.compareToIgnoreCase(b.name));
        System.out.println(people);
        Collections.sort(people, (a, b) -> a.age < b.age ? -1 : a.age == b.age ? 0 : 1);
        System.out.println(people);
    }
}
于 2010-05-15T06:32:40.767 に答える
40

People implements Comparable<People>代わりに使用してください。これは の自然な順序を定義しPeopleます。

AComparator<People>も追加で定義できますがPeople implements Comparator<People>、正しい方法ではありません。

の 2 つのオーバーロードCollections.sortは異なります。

  • <T extends Comparable<? super T>> void sort(List<T> list)
    • Comparable自然順序付けを使用してオブジェクトを並べ替えます
  • <T> void sort(List<T> list, Comparator<? super T> c)
    • 互換性を使用して何でも並べ替えますComparator

a をソートしようとして、2 つを混同していますComparator(これが、 が意味をなさない理由ですPerson implements Comparator<Person>)。繰り返しますが、 を使用するCollections.sortには、次のいずれかが true である必要があります。

  • タイプはComparable( 1-arg を使用sort)でなければなりません
  • タイプのComparatorを指定する必要があります (2-args を使用sort)

関連する質問


また、新しいコードでは生の型を使用しないでください。生の型は安全ではなく、互換性のためにのみ提供されています。

つまり、これの代わりに:

ArrayList peps = new ArrayList(); // BAD!!! No generic safety!

次のような型安全なジェネリック宣言を使用する必要がありました。

List<People> peps = new ArrayList<People>(); // GOOD!!!

その後、コードがコンパイルされないことがわかります!! コードに何か問題があるため ( Persondoes not implements Comparable<Person>)、それは良いことですが、生の型を使用したため、コンパイラは this をチェックせず、代わりにClassCastException実行時に a を取得します!!!

これにより、新しいコードでは常に型保証されたジェネリック型を使用するように説得されるはずです。いつも。

こちらもご覧ください

于 2010-05-15T06:25:38.887 に答える
21

完全を期すために、簡単なワンライナーのcompare方法を次に示します。

Collections.sort(people, new Comparator<Person>() {
    @Override
    public int compare(Person lhs, Person rhs) {  
        return Integer.signum(lhs.getId() - rhs.getId());  
    }
});
于 2014-12-10T19:30:57.807 に答える
4

Comparator ではなく Comparable を実装します。compareTo メソッドを実装する必要があります。しかし、あなたは近くにいます。Comparator は「サードパーティ」の比較ルーチンです。比較可能とは、このオブジェクトを別のオブジェクトと比較できることです。

public int compareTo(Object obj1) {
  People that = (People)obj1;
  Integer p1 = this.getId();
  Integer p2 = that.getid();

  if (p1 > p2 ){
   return 1;
  }
  else if (p1 < p2){
   return -1;
  }
  else
   return 0;
 }

念のため、ここで getId の null をチェックすることをお勧めします。

于 2010-05-15T06:29:45.150 に答える
1

ソリューションは次の方法で最適化できます。まず、クラス People の実装が外部の世界に公開されないように、フィールドのスコープがそれを囲むクラス TestPeople であるため、プライベート 内部クラスを使用します。これは、並べ替えられた人のリストを期待する API を作成するという観点から理解できます。次に、コードを削減する Lamba 式 (Java 8) を使用するため、開発の労力がかかります。

したがって、コードは次のようになります。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class TestPeople {
    public static void main(String[] args) {
        ArrayList<People> peps = new ArrayList<>();// Be specific, to avoid
                                                    // classCast Exception

        TestPeople test = new TestPeople();

        peps.add(test.new People(123, "M", 14.25));
        peps.add(test.new People(234, "M", 6.21));
        peps.add(test.new People(362, "F", 9.23));
        peps.add(test.new People(111, "M", 65.99));
        peps.add(test.new People(535, "F", 9.23));

        /*
         * Collections.sort(peps);
         * 
         * for (int i = 0; i < peps.size(); i++){
         * System.out.println(peps.get(i)); }
         */

        // The above code can be replaced by followin:

        peps.sort((People p1, People p2) -> p1.getid() - p2.getid());

        peps.forEach((p) -> System.out.println(" " + p.toString()));

    }

    private class People {
        private int id;

        @Override
        public String toString() {
            return "People [id=" + id + ", info=" + info + ", price=" + price + "]";
        }

        private String info;
        private double price;

        public People(int newid, String newinfo, double newprice) {
            setid(newid);
            setinfo(newinfo);
            setprice(newprice);
        }

        public int getid() {
            return id;
        }

        public void setid(int id) {
            this.id = id;
        }

        public String getinfo() {
            return info;
        }

        public void setinfo(String info) {
            this.info = info;
        }

        public double getprice() {
            return price;
        }

        public void setprice(double price) {
            this.price = price;
        }
    }
}
于 2016-11-24T15:39:38.047 に答える