¿Por qué TreeSet lanza ClassCastException?

En el código siguiente, bash agregar dos objetos para empleados

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

Pero el resultado es 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) 

Pero si cambio a.

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

O

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

Entonces el resultado es éxito, no hay excepción. No estoy haciendo ninguna actividad de fundición de clase en el código anterior. Ayúdame a descubrir la causa y sugiéreme la solución.

O bien el Employee debe implementar Comparable , o necesita proporcionar un comparador al crear el TreeSet .

Esto se SortedSet en la documentación de SortedSet :

Todos los elementos insertados en un conjunto ordenado deben implementar la interfaz Comparable (o ser aceptado por el comparador especificado). Además, todos estos elementos deben ser mutuamente comparables: e1.compareTo(e2) (o comparator.compare(e1, e2) ) no debe arrojar una ClassCastException para ningún elemento e1 y e2 en el conjunto ordenado. Los bashs de infringir esta restricción harán que el método ofensivo o la invocación del constructor ClassCastException una ClassCastException .

Si no cumple con estos requisitos, el conjunto ordenado no sabrá cómo comparar sus elementos y no podrá funcionar.

Así que implemente la interfaz Comparable al objeto Employee como se necesita cuando está usando TreeSet, porque TreeSet desea mantener los elementos ordenados.

TreeSet requiere que los elementos implementen Comparable si no se establece un Comparator personalizado. HashSet utiliza el contrato equals / hashCode en su lugar.

Puede agregar solo un elemento en TreeSet que no implementa Comparable porque no necesita ser comparado con otros elementos.

Eche un vistazo a los códigos fuente TreeMap.put(K key, V value) y verá claramente las razones detrás de todas sus preguntas ( TreeSet se basa en TreeMap , de ahí la referencia de origen).

Desde TreeSet # add (E) JavaDoc:

Lanza : ClassCastException – si el objeto especificado no se puede comparar con los elementos actualmente en este conjunto

Básicamente, lo que necesita es dejar que Employee implemente Comparable o proporcionar un Comparator al objeto TreeSet .

Si TreeMap código de TreeMap , verá que si el comparador no se encontró dentro del objeto Map , intentará enviar la clave (su objeto Employee ) directamente a Comparator :

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

TreeSet es una implementación de SortedSet . Puede permitir que Employee implemente la interfaz Comparable o proporcionar un Comparator apropiado para su TreeSet :

 Set s = new TreeSet(new EmployeeComparator()); 
 //class Employee public class Employee implements Comparable{ 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 emp =new TreeSet(); 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