J'essaie d'ajouter deux objets 'Employé' à un TreeSet:
Set<Employee> s = new TreeSet<Employee>();
s.add(new Employee(1001));
s.add(new Employee(1002));
Mais il lève une exception 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)
Mais si je n’ajoute qu’un seul objet à l’arbre:
Set<Employee> s = new TreeSet<Employee>();
s.add(new Employee(1001));
Ou si j'utilise plutôt un HashSet:
Set<Employee> s = new HashSet<Employee>();
s.add(new Employee(1001));
s.add(new Employee(1002));
Alors c'est réussi. Pourquoi l'exception se produit et comment puis-je résoudre le problème?
Employee
doit implémenter Comparable
, ou vous devez fournir un comparateur lors de la création de TreeSet
.
Ceci est expliqué dans la documentation de SortedSet
:
Tous les éléments insérés dans un ensemble trié doivent implémenter l'interface
Comparable
(ou être acceptés par le comparateur spécifié). De plus, tous ces éléments doivent être comparables entre eux:e1.compareTo(e2)
(oucomparator.compare(e1, e2)
) ne doit pas jeter uneClassCastException
pour aucun élémente1
ete2
dans l'ensemble trié. Si vous tentez de ne pas respecter cette restriction, la méthode ou l’appel du constructeur incriminé jettera uneClassCastException
.
Si vous ne remplissez pas ces conditions, l'ensemble trié ne saura pas comparer ses éléments et ne pourra pas fonctionner.
TreeSet
requiert des éléments pour implémenter l'interface Comparable
si une Comparator
personnalisée n'est pas définie. HashSet
utilise plutôt le contrat equals
/hashCode
.
Vous ne pouvez ajouter qu'un seul élément dans TreeSet
qui n'implémente pas Comparable
car il n'a pas besoin d'être comparé à d'autres éléments.
Examinez le code source TreeMap.put(K key, V value)
et vous verrez clairement les raisons de toutes vos questions (TreeSet
est basé sur TreeMap
, d’où la référence source).
De TreeSet # add (E) JavaDoc:
Lance: ClassCastException - si l'objet spécifié ne peut pas être par rapport aux éléments actuellement dans cet ensemble
En gros, vous avez besoin de laisser Employee
implémenter Comparable
ou de fournir un Comparator
à l’objet TreeSet
.
Si vous vérifiez le code TreeMap
, vous verrez que si le comparateur n'a pas été trouvé dans l'objet Map
, il essaiera de convertir la clé (votre objet Employee
) directement en Comparator
:
...
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
Donc, implémentez l’interface Comparable avec l’objet Employé comme vous le souhaitez lorsque vous utilisez TreeSet, car TreeSet souhaite conserver les éléments triés.
TreeSet
est une implémentation de SortedSet
. Vous pouvez laisser Employee
implémenter l'interface Comparable
ou fournir une Comparator
appropriée à votre TreeSet
:
Set<Employee> s = new TreeSet<Employee>(new EmployeeComparator());