Почему TreeSet выбрасывает ClassCastException

В приведенном ниже коде я пытаюсь добавить два объекта employee

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

Но результат java.lang.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)

Но если я перейду на.

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 должен реализовать Comparable, либо вам нужно предоставить компаратор, когда создавая TreeSet.

Это указано в документации для SortedSet:

Все элементы, вставленные в отсортированный набор, должны реализовывать интерфейс Comparable (или быть принятым указанным компаратором). Кроме того, все такие элементы должны быть взаимно сопоставимыми: e1.compareTo(e2) (или comparator.compare(e1, e2)) не должны бросать ClassCastException для любых элементов e1 и e2 в отсортированном наборе. Попытки нарушить это ограничение вызовут способ нарушения или вызов конструктора, чтобы выбросить ClassCastException.

Если вы не выполняете эти требования, сортированный набор не будет знать, как сравнить его элементы и не сможет функционировать.

Ответ 2

Итак, реализуйте интерфейс Comparable для объекта Employee, который необходим, когда вы используете TreeSet, потому что TreeSet хочет сохранить отсортированные элементы.

Ответ 3

TreeSet требуется для элементов для реализации Comparable, если пользовательский Comparator не установлен. HashSet использует вместо этого контракт equals/hashCode.

Вы можете добавить только один элемент в TreeSet, который не реализует Comparable, потому что его не нужно сравнивать с другими элементами.

Взгляните на исходные коды TreeMap.put(K key, V value), и вы ясно увидите причины, лежащие в основе всех ваших вопросов (TreeSet основан на TreeMap, следовательно, исходная ссылка).

Ответ 4

TreeSet представляет собой реализацию SortedSet. Вы можете либо позволить Employee реализовать интерфейс Comparable, либо предоставить соответствующий Comparator для вашего TreeSet:

Set<Employee> s = new TreeSet<Employee>(new EmployeeComparator());

Ответ 5

Из TreeSet # add (E) JavaDoc:

Throws: ClassCastException - если указанный объект не может быть по сравнению с элементами, находящимися в этом наборе

В основном вам нужно позволить Employee реализовать Comparable или предоставить Comparator объекту TreeSet.

Если вы проверите код TreeMap, вы увидите, что если компаратор не был найден в объекте Map, он попытается применить ключ (ваш объект Employee) непосредственно к Comparator:

...
Comparable<? super K> k = (Comparable<? super K>) key;
...

Ответ 6

//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