Java 为什么TreeSet抛出ClassCastException?
我正在尝试将两个“Employee”对象添加到树集中:Java 为什么TreeSet抛出ClassCastException?,java,exception,collections,set,treeset,Java,Exception,Collections,Set,Treeset,我正在尝试将两个“Employee”对象添加到树集中: Set<Employee> s = new TreeSet<Employee>(); s.add(new Employee(1001)); s.add(new Employee(1002)); 但如果我只向树集添加一个对象: Set<Employee> s = new TreeSet<Employee>(); s.add(new Employee(1001)); Set s=new Tre
Set<Employee> s = new TreeSet<Employee>();
s.add(new Employee(1001));
s.add(new Employee(1002));
但如果我只向树集添加一个对象:
Set<Employee> s = new TreeSet<Employee>();
s.add(new Employee(1001));
Set s=new TreeSet();
s、 增加(新员工(1001));
或者如果我改用哈希集:
Set<Employee> s = new HashSet<Employee>();
s.add(new Employee(1001));
s.add(new Employee(1002));
Set s=newhashset();
s、 增加(新员工(1001));
s、 增加(新员工(1002));
那么它就成功了。为什么会发生异常?我如何修复它?因此,在使用TreeSet时,根据需要实现Employee对象的可比接口,因为TreeSet希望保持元素的排序。要么必须实现
Employee
,要么在创建
这在以下文件中有详细说明:
插入排序集的所有元素必须实现可比
接口(或由指定的比较器接受)。此外,所有这些元素必须相互可比:e1.compareTo(e2)
(或comparator.compare(e1,e2)
)不得对排序集中的任何元素e1
和e2
抛出ClassCastException
。违反此限制的尝试将导致有问题的方法或构造函数调用抛出ClassCastException
如果不满足这些要求,则排序集将不知道如何比较其元素,并且将无法运行。
TreeSet
要求元素在未设置自定义比较器的情况下实现可比接口HashSet
使用equals
/hashCode
契约代替
您只能将一个元素添加到TreeSet
中,该元素不实现compariable
,因为它不需要与其他元素进行比较
查看TreeMap.put(K键,V值)
源代码,您将清楚地看到所有问题背后的原因(TreeSet
基于TreeMap
,因此是源代码参考) TreeSet
是SortedSet
的一个实现。您可以让Employee
实现compariable
界面,或者为您的TreeSet
提供适当的比较器:
Set<Employee> s = new TreeSet<Employee>(new EmployeeComparator());
Set s=new TreeSet(new EmployeeComparator());
来自JavaDoc:
抛出:ClassCastException-如果无法调用指定的对象
与此集合中当前的元素相比
基本上,您需要让Employee
实现compariable
或为TreeSet
对象提供一个比较器
如果您选中TreeMap
code,您将看到如果在Map
对象中找不到比较器,它将尝试将键(您的Employee
对象)直接强制转换到比较器
:
...
Comparable<? super K> k = (Comparable<? super K>) key;
...
。。。
可比较的//类员工
公共类Employee实现了可比较的{
int-id;
雇员(内部id){
这个.id=id;
}
public int compareTo(Employee e){//实现抽象方法。
如果(id>e.id){
返回1;
}
返回0;
}
//类树集
设置emp=新树集();
员工eobj1=新员工(2);
员工eobj2=新员工(3);
emp.add(eobj1);
emp.add(eobj2);
学生(ss:emp){
System.out.println(ss.rollno);
}
}
//产出:2
// 3
可压缩接口的实现是不是可以改进?@FireFly:不,不是。您可以提供一个比较器。看到我的答案了。好吧,要么Employee必须实现comparable,要么我需要创建一个外部comparator,对吗?但在本例中Employee类不实现comparable,并且没有外部comparator。当我添加一个元素时,一切都很好。当我添加第二个元素时,问题就开始了。问题是,如果您描述的场景是强制性的,那么为什么编译器会编译该程序。@FireFly:这是强制性的,但在集合实际需要比较元素之前(当您尝试添加第二个元素时)不会强制执行。@FireFly:没有外部比较器,该类采用专门化参数来实现可比较的接口。任何一个都必须存在,但编译器不能强制这样的约束,因为在编译时不可能这样做。@NPE感谢您的回答解释。我在面试中被问到,但我没有回答。你需要相信错误消息是正确的Employee无法转换为java.lang.Compariable
是问题所在。当您有一个元素时,没有什么可比较的,因此它不会检测到问题。HashSet不使用Compariable,因此也不检查它。Employee eobj1=新员工(3);员工eobj2=新员工(2)//o/p:3只
...
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