I have a class Contact that I have displayed below. I want each Contact object to have a list of other Contacts. I chose a TreeSet
because I'd like to avoid duplicate Contacts in the same list. My Contact class implements Comparable
and has a constructed compareTo() method that compares instance String variables. I understand the compareTo method is used when adding to a TreeSet because added elements are immediately sorted.
When I try to add a Contact object from a Contact[] (see my setContacts() method below) to my TreeSet, I receive a ClassCastException
. My system.out messages is:
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)
What I do not understand is that nowhere in any of the classes I have built do I try to convert anything into a String. Below is my entire Contact class.
Does anyone see anything wrong or see why the exception is occuring?
I'd be happy to post more code if someone tells me what else might be relevant. I don't know what else would be important to see. Thanks in advance.
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;
}
}
The answer is right here in Collator.java:
public int compare(Object o1, Object o2) {
return compare((String)o1, (String)o2);
}
It's not immediately obvious to me but why on Earth are you passing in your own Collator? Are you dealing with Non ascii?
You also have a inconsistency here: compareTo() == 0 SHOULD be the same as equals() especially since in both cases the only thing you seem to care about is 'name'
So, on the one hand you state you want to remove identical entries and thus you use Comparative identity but then you use a Collator which can definitely produce inconsistent results with equals.
If all you want is remove redundancy than skip the Collator and either use HashSet or TreeSet with no Collator
Alternatively if you MUST use Collated names then use a
TreeMap<String,Contact> contacts = new TreeMap<String,Contact>(Collator.getInstance());
contacts.put(contact.getName(),contact);
You can then use:
Collection<Contact> uniqueContacts = contacts.values();