Java 为什么TreeSet抛出ClassCastException?

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

我正在尝试将两个“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 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