Treeset.add()时ClassCastException,尽管实现与compareTo方法相当

时间:2013-04-18 18:44:07

标签: java classcastexception comparable compareto

我有一个班级联系人,我在下面显示。我希望每个Contact对象都有一个其他Contacts的列表。我选择了TreeSet,因为我想避免在同一个列表中重复使用联系人。 My Contact类实现Comparable并且具有构造的compareTo()方法,用于比较实例String变量。我理解在添加到TreeSet时使用了compareTo方法,因为添加的元素会立即排序。

当我尝试将Contact [](请参阅下面的setContacts()方法)中的Contact对象添加到我的TreeSet时,我收到ClassCastException。我的system.out消息是:

Exception in thread "main" java.lang.ClassCastException: shared.Contact cannot be cast to java.lang.String
at java.text.Collator.compare(Unknown Source)
at java.util.TreeMap.compare(Unknown Source)
at java.util.TreeMap.put(Unknown Source)
at java.util.TreeSet.add(Unknown Source)
at shared.Contact.setContacts(Contact.java:51) <-- right here is the TreeSet.add()
at server.Server.readInContacts(Server.java:191)
at server.Server.main(Server.java:51)

我不明白的是,在我构建的任何类中都没有,我尝试将任何东西转换为String。以下是我的整个Contact课程。

有没有人看到任何错误或者看到为什么会发生异常?

如果有人告诉我其他可能相关的内容,我会很乐意发布更多代码。我不知道还有什么重要的。提前谢谢。

package shared;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.Collator;
import java.util.LinkedList;
import java.util.TreeSet;

public class Contact implements Serializable, Comparable<Contact>{

    private static final long serialVersionUID = 1L;
    private String name;
    private boolean online;
    private TreeSet<Contact> contacts;
    private ObjectOutputStream oos;
    private ObjectInputStream ois;


    public Contact(String name){
        this(name, null, null);
    }
    public Contact (String name, ObjectInputStream ois, ObjectOutputStream oos){
        this.name = name;
        this.ois = ois;
        this.oos = oos;
        contacts = new TreeSet<Contact>(Collator.getInstance());
    }
    public String getName(){
        return name;
    }
    public void logIn(ObjectInputStream ois, ObjectOutputStream oos){
        this.ois = ois;
        this.oos = oos;
    }
    public ObjectInputStream getObjectInputStream(){
        return ois;
    }
    public ObjectOutputStream getObjectOutputStream(){
        return oos;
    }
    public void setOnlineStatus(boolean status){
        online = status;
    }
    public boolean isOnline(){
        return online;
    }
    public void setContacts(Contact[] contacts){
        this.contacts.clear();
        for (Contact c: contacts){
            this.contacts.add(c);  <-- right here is where my exception occurs
        }
    }

    @Override
    public int compareTo(Contact c){
        return this.name.compareTo(c.getName());
    }

    public boolean equals(Object o){
        Contact c = (Contact)o;
        return this.name.equals(c.getName());
    }

    public void addContact(Contact c){
        LinkedList<Contact> list = new LinkedList<Contact>();
        for (Contact contact: contacts){
            list.add(contact);
        }
    }
    public Contact[] getContacts(){
        return contacts.toArray(new Contact[0]);
    }





    public int hashCode(){
        return name.hashCode();
    }

    public String toString(){
        return this.name;
    }




}

2 个答案:

答案 0 :(得分:2)

答案就在Collat​​or.java:

public int compare(Object o1, Object o2) {
return compare((String)o1, (String)o2);
}

这对我来说不是很明显,但为什么你在地球上传递自己的Collat​​or? 你在处理Non ascii吗?

你在这里也有一个不一致的地方:compareTo()== 0应该和equals()一样,特别是因为在这两种情况下,你似乎唯一关心的是'name'

因此,一方面,您声明要删除相同的条目,因此您使用比较身份但是您使用的Collat​​or肯定会产生与equals不一致的结果。

如果你想要的只是删除冗余而不是跳过Collat​​or并且使用没有Collat​​or的HashSet或TreeSet

或者,如果你必须使用整理的名称,那么使用

TreeMap<String,Contact> contacts = new TreeMap<String,Contact>(Collator.getInstance());
contacts.put(contact.getName(),contact);

然后您可以使用:

Collection<Contact> uniqueContacts = contacts.values();

答案 1 :(得分:-1)

c.getName()返回一个String然后用这个调用equals ..所以String被传递给equals ...

第一行等于尝试将String转换为Contact ... Boom

compare方法将在它尝试比较的对象上调用equals。