it-swarm.com.de

Warum löst TreeSet eine ClassCastException aus?

Ich versuche, einem TreeSet zwei 'Employee'-Objekte hinzuzufügen:

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

Aber es löst eine ClassCastException aus:

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)

Aber wenn ich nur ein Objekt zum TreeSet hinzufüge:

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

Oder wenn ich stattdessen ein HashSet verwende:

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

Dann ist es erfolgreich. Warum tritt die Ausnahme auf und wie behebe ich sie?

16
Rais Alam

Entweder muss EmployeeComparable implementieren, oder Sie müssen einen Vergleicher bereitstellen , wenn Sie die TreeSet erstellen.

Dies ist in der Dokumentation für SortedSet beschrieben:

Alle Elemente, die in eine sortierte Gruppe eingefügt werden, müssen die Comparable-Schnittstelle implementieren (oder vom angegebenen Vergleicher akzeptiert werden). Darüber hinaus müssen alle diese Elemente miteinander vergleichbar sein: e1.compareTo(e2) (oder comparator.compare(e1, e2)) darf keine ClassCastException für Elemente e1 und e2 in der sortierten Menge werfen. Wenn Sie versuchen, gegen diese Einschränkung zu verstoßen, wird durch den Aufruf der betreffenden Methode oder des Konstruktors eine ClassCastException ausgelöst.

Wenn Sie diese Anforderungen nicht erfüllen, kann das sortierte Set nicht die Elemente vergleichen und kann nicht funktionieren.

22
NPE

TreeSet erfordert, dass Elemente die Comparable-Schnittstelle implementieren, wenn kein benutzerdefiniertes Comparator festgelegt ist. HashSet verwendet stattdessen den equals/hashCode-Vertrag.

Sie können nur ein Element zu TreeSet hinzufügen, das Comparable nicht implementiert, da es nicht mit anderen Elementen verglichen werden muss. 

Werfen Sie einen Blick auf den TreeMap.put(K key, V value)-Quellcode und Sie werden die Gründe für alle Ihre Fragen deutlich erkennen (TreeSet basiert auf TreeMap, daher die Quellreferenz). 

2
denis.solonenko

Aus TreeSet # add (E) JavaDoc:

Throws : ClassCastException - wenn das angegebene Objekt nicht mit Verglichen werden kann, verglichen mit den Elementen, die sich aktuell in dieser Gruppe befinden

Grundsätzlich müssen Sie EmployeeComparable implementieren lassen oder eine Comparator für das TreeSet-Objekt bereitstellen.

Wenn Sie den TreeMap-Code überprüfen, werden Sie feststellen, dass wenn der Vergleicher nicht innerhalb des Map-Objekts gefunden wurde, der Schlüssel (Ihr Employee-Objekt) direkt in Comparator umgewandelt wird: 

...
Comparable<? super K> k = (Comparable<? super K>) key;
...
1
//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
0
charu

Implementieren Sie daher die Comparable-Schnittstelle für das Employee-Objekt, wie es bei der Verwendung von TreeSet erforderlich ist, da TreeSet die Elemente sortiert halten möchte.

0
Martin V.

TreeSet ist eine Implementierung von SortedSet. Sie können entweder Employee das Interface Comparable implementieren lassen oder eine geeignete Comparator für Ihre TreeSet angeben:

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