[英]Why does TreeSet throw a ClassCastException?
我試圖將兩個'Employee'對象添加到TreeSet:
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添加一個對象:
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
。
如果您不滿足這些要求,則排序集將不知道如何比較其元素並且將無法運行。
如果未設置自定義Comparator
TreeSet
需要元素來實現Comparable
接口。 HashSet
使用equals
/ hashCode
合約。
您只能在TreeSet
添加一個不實現Comparable
元素,因為它不需要與其他元素進行比較。
看看TreeMap.put(K key, V value)
源代碼,您將清楚地看到所有問題背后的原因( TreeSet
基於TreeMap
,因此是源參考)。
從TreeSet #add(E) JavaDoc:
拋出 :ClassCastException - 如果指定的對象無法與此set中當前的元素進行比較
基本上你需要的是讓Employee
實現Comparable
或者為TreeSet
對象提供一個Comparator
。
如果檢查TreeMap
代碼,您將看到如果在Map
對象中找不到比較器,它將嘗試將密鑰(您的Employee
對象)直接轉換為Comparator
:
...
Comparable<? super K> k = (Comparable<? super K>) key;
...
因此,當您使用TreeSet時,需要實現與Employee對象的Comparable接口,因為TreeSet希望保持元素的排序。
TreeSet
是SortedSet
一個實現。 您可以讓Employee
實現Comparable
接口,也可以為TreeSet
提供適當的Comparator
:
Set<Employee> s = new TreeSet<Employee>(new EmployeeComparator());
//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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.