为什么 TreeSet 会抛出 ClassCastException?

2022-09-02 03:52:12

我正在尝试将两个“员工”对象添加到树集:

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));

或者,如果我使用哈希集代替:

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

然后它成功了。为什么会发生异常,我该如何解决?


答案 1

要么必须实现可比性,要么需要在创建树集提供比较器Employee

这在排序集的文档中进行了详细说明:

插入到排序集中的所有元素都必须实现接口(或被指定的比较器接受)。此外,所有这些元素都必须相互比较:(或)不得为任何元素和排序集合抛出 a。尝试违反此限制将导致违规方法或构造函数调用引发 .Comparablee1.compareTo(e2)comparator.compare(e1, e2)ClassCastExceptione1e2ClassCastException

如果您不满足这些要求,则排序的集合将不知道如何比较其元素,并且将无法运行。


答案 2

TreeSet如果未设置自定义,则需要元素来实现接口。 使用 / 合约代替。ComparableComparatorHashSetequalshashCode

您只能添加一个未实现的元素,因为它不需要与其他元素进行比较。TreeSetComparable

看一下源代码,你会清楚地看到所有问题背后的原因(基于,因此是源参考)。TreeMap.put(K key, V value)TreeSetTreeMap