web-dev-qa-db-ja.com

TreeSetがClassCastExceptionをスローするのはなぜですか?

TreeSetに2つの 'Employee'オブジェクトを追加しようとしています。

Set<Employee> s = new TreeSet<Employee>();
s.add(new Employee(1001));
s.add(new Employee(1002));

ただし、ClassCastExceptionがスローされます。

Exception in thread "main" Java.lang.ClassCastException: Employee cannot be cast to Java.lang.Comparable
    at Java.util.TreeMap.put(TreeMap.Java:542)
    at Java.util.TreeSet.add(TreeSet.Java:238)
    at MyClient.main(MyClient.Java:9)

しかし、TreeSetにオブジェクトを1つだけ追加した場合:

Set<Employee> s = new TreeSet<Employee>();
s.add(new Employee(1001));

または、代わりにHashSetを使用する場合:

Set<Employee> s = new HashSet<Employee>();
s.add(new Employee(1001));
s.add(new Employee(1002));

その後、成功します。なぜ例外が発生し、どうすれば修正できますか?

18
Rais Alam

EmployeeComparable を実装する必要があるか、または コンパレータを提供する必要がありますTreeSet を作成するとき。

これは、 SortedSet のドキュメントで詳しく説明されています。

ソートされたセットに挿入されるすべての要素は、Comparableインターフェースを実装する必要があります(または、指定されたコンパレーターによって受け入れられる必要があります)。さらに、そのような要素はすべて相互に比較可能でなければなりません:e1.compareTo(e2)(またはcomparator.compare(e1, e2))は、ソートされたセットの要素e1およびe2に対してClassCastExceptionをスローしてはなりません。 。この制限に違反しようとすると、問題のあるメソッドまたはコンストラクターがClassCastExceptionをスローします。

これらの要件を満たさない場合、ソートされたセットはその要素を比較する方法を認識できず、機能できなくなります。

23
NPE

TreeSetには、カスタムComparableが設定されていない場合、Comparatorインターフェースを実装するための要素が必要です。 HashSetは代わりにequals/hashCodeコントラクトを使用します。

他の要素と比較する必要がないため、TreeSetを実装しないComparableに追加できる要素は1つだけです。

TreeMap.put(K key, V value)ソースコードを見ると、すべての質問の背後にある理由が明確にわかります(TreeSetTreeMapに基づいているため、ソース参照です)。

2
denis.solonenko

From TreeSet#add(E) JavaDoc:

Throws:ClassCastException-指定されたオブジェクトが現在このセットにある要素と比較できない場合

基本的に必要なのは、EmployeeComparableを実装させるか、ComparatorオブジェクトにTreeSetを提供することです。

TreeMapコードをチェックすると、Mapオブジェクト内にコンパレータが見つからなかった場合、キー(Employeeオブジェクト)を直接にキャストしようとすることがわかります。 Comparator

...
Comparable<? super K> k = (Comparable<? super K>) key;
...
1
//class Employee
    public class Employee implements Comparable<Employee>{
    int id;

    Employee(int id){
    this.id=id;
    }

    public int compareTo(Employee e){ //implementing abstract method.
    if(id>e.id){
    return 1;
    }
    return 0;
    }


//class TreeSet

    Set<Employee> emp =new TreeSet<Employee>();

    Employee eobj1 = new Employee(2);
    Employee eobj2 = new Employee(3);
    emp.add(eobj1);
    emp.add(eobj2);

    for (Student ss:emp) {
    System.out.println(ss.rollno);
    }
}
//output: 2
//        3
0
charu

したがって、TreeSetは要素を並べ替えたままにする必要があるため、TreeSetを使用するときに必要になるため、EmployeeオブジェクトにComparableインターフェイスを実装します。

0
Martin V.

TreeSetSortedSetの実装です。 EmployeeComparableインターフェースを実装させるか、Comparatorに適切なTreeSetを提供できます。

Set<Employee> s = new TreeSet<Employee>(new EmployeeComparator());
0
Marco Forberg