MarioDS
MarioDS

Reputation: 13063

Compare object with deserialised object

I have a Swing application with a JList that works with a custom listmodel.

The model has an ArrayList to store the objects used. The situation is as follows:

Upon closing the application, all objects in the listmodel are serialized (in the default way, the class just implements Serializable), and written to a file via an ObjectOutputStream. When the application starts up, all objects are read from the file and stored in my custom ListModel again.

I'm trying to add a feature to let the user import objects too, from a file he specifies. A static method in another class reads all objects from the file, and returns them in an ArrayList. I then use the for-each loop in my MainForm class to store each object from the returned ArrayList in the ListModel. In the loop, I want to check whether the ListModel already contains a certain object, but this does not work.

In code, I'm doing the following:

for(MyObject o: readObjects) {
    if(!myListModel.contains(o)) //listmodel just calls contains() on its ArrayList
        myListModel.addElement(o);
}

However, even when the object is already in the ArrayList (I keep importing objects from the same file), they are still added.

The question is, how come objects are not equal anymore when deserialized, and is there a way to compare them anyway?

Upvotes: 0

Views: 2799

Answers (2)

Eric C.
Eric C.

Reputation: 3368

Here is a simple java object

public class MyObject {

private String firstname;
private String lastname;
private String email;

public String getFirstname() {
    return firstname;
}
public void setFirstname(String firstname) {
    this.firstname = firstname;
}
public String getLastname() {
    return lastname;
}
public void setLastname(String lastname) {
    this.lastname = lastname;
}
public String getEmail() {
    return email;
}
public void setEmail(String email) {
    this.email = email;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result
            + ((firstname == null) ? 0 : firstname.hashCode());
    result = prime * result
            + ((lastname == null) ? 0 : lastname.hashCode());
    return result;
}
@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    MyObject other = (MyObject) obj;
    if (firstname == null) {
        if (other.firstname != null)
            return false;
    } else if (!firstname.equals(other.firstname))
        return false;
    if (lastname == null) {
        if (other.lastname != null)
            return false;
    } else if (!lastname.equals(other.lastname))
        return false;
    return true;
}
}

(hashcode and equals auto generated by eclipse)

If you look at equals() method, you will see that 2 objects are compared on the fields firstname and lastname, and only those 2. This means that if you insert objects of this type in a list, you will be able to use contains(Object o) and if an object contains the same firstname and lastname, you'll find it.

Upvotes: 2

assylias
assylias

Reputation: 328578

You need to override the equals and hashcode method of your object (many examples are available on SO, for example here.

Once you have done that, the contains method of List will behave as you expect. Your problem does not seem related to serialization. In other words, the following code:

List<MyObject> list = new ArrayList<MyObject>();
list.add(new MyObject());
System.out.println(list.contains(new MyObject()));

will print false if you don't override equals & hashcode whereas it might print true if you do (depending on whether your equals method consider those 2 new MyObject() to be equals or not). Your IDE should have a way to auto generate the code for you.

Once you are happy that the contains method works as expected on your objects, serialising/deserialising should work as expected.

Upvotes: 1

Related Questions