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));
その後、成功します。なぜ例外が発生し、どうすれば修正できますか?
Employee
は Comparable
を実装する必要があるか、または コンパレータを提供する必要がありますTreeSet
を作成するとき。
これは、 SortedSet
のドキュメントで詳しく説明されています。
ソートされたセットに挿入されるすべての要素は、
Comparable
インターフェースを実装する必要があります(または、指定されたコンパレーターによって受け入れられる必要があります)。さらに、そのような要素はすべて相互に比較可能でなければなりません:e1.compareTo(e2)
(またはcomparator.compare(e1, e2)
)は、ソートされたセットの要素e1
およびe2
に対してClassCastException
をスローしてはなりません。 。この制限に違反しようとすると、問題のあるメソッドまたはコンストラクターがClassCastException
をスローします。
これらの要件を満たさない場合、ソートされたセットはその要素を比較する方法を認識できず、機能できなくなります。
TreeSet
には、カスタムComparable
が設定されていない場合、Comparator
インターフェースを実装するための要素が必要です。 HashSet
は代わりにequals
/hashCode
コントラクトを使用します。
他の要素と比較する必要がないため、TreeSet
を実装しないComparable
に追加できる要素は1つだけです。
TreeMap.put(K key, V value)
ソースコードを見ると、すべての質問の背後にある理由が明確にわかります(TreeSet
はTreeMap
に基づいているため、ソース参照です)。
From TreeSet#add(E) JavaDoc:
Throws:ClassCastException-指定されたオブジェクトが現在このセットにある要素と比較できない場合
基本的に必要なのは、Employee
にComparable
を実装させるか、Comparator
オブジェクトにTreeSet
を提供することです。
TreeMap
コードをチェックすると、Map
オブジェクト内にコンパレータが見つからなかった場合、キー(Employee
オブジェクト)を直接にキャストしようとすることがわかります。 Comparator
:
...
Comparable<? super K> k = (Comparable<? super K>) key;
...
//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
したがって、TreeSetは要素を並べ替えたままにする必要があるため、TreeSetを使用するときに必要になるため、EmployeeオブジェクトにComparableインターフェイスを実装します。
TreeSet
はSortedSet
の実装です。 Employee
にComparable
インターフェースを実装させるか、Comparator
に適切なTreeSet
を提供できます。
Set<Employee> s = new TreeSet<Employee>(new EmployeeComparator());