You should override hashCode() and equals() method. you can generate these from IDE.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MyData)) return false;
MyData myData = (MyData) o;
if (id != myData.id) return false;
if (!desc.equals(myData.desc)) return false;
if (!name.equals(myData.name)) return false;
return true;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + name.hashCode();
result = 31 * result + desc.hashCode();
return result;
}
Now you can compare the objects. That's it.
Answer from Ruchira Gayan Ranaweera on Stack OverflowYou should override hashCode() and equals() method. you can generate these from IDE.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MyData)) return false;
MyData myData = (MyData) o;
if (id != myData.id) return false;
if (!desc.equals(myData.desc)) return false;
if (!name.equals(myData.name)) return false;
return true;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + name.hashCode();
result = 31 * result + desc.hashCode();
return result;
}
Now you can compare the objects. That's it.
Conventional way is to override equals and hashCode methods. Java standard libraries, for instance Map s, List s, Set s use the equals and hashCode functions for equality testing. The code below also null-safe;
Here is the code for your case;
public class MyData {
int id;
String name;
String desc;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyData myData = (MyData) o;
if (id != myData.id) return false;
if (desc != null ? !desc.equals(myData.desc) : myData.desc != null) return false;
if (name != null ? !name.equals(myData.name) : myData.name != null) return false;
return true;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (desc != null ? desc.hashCode() : 0);
return result;
}
}
and you can test the equality by;
....
Mydata d1 = new...
Mydata d2 = new...
boolean areTheyEqual = d1.equals(d2);
However if you are not allowed to make a compare field by field then you can use byte arrays, there is no need to convert them to strings.
.....
public boolean equals(Object other){
if (this == other) return true;
if (other == null || getClass() != other.getClass()) return false;
byte[] bytesThis = serialize(this);
byte[] bytesOther = serialize(other);
if(bytesOther.length != bytesThis.length) return false;
return Arrays.equals(bytesThis, bytesOther);
}
public static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(b);
o.writeObject(obj);
return b.toByteArray();
}
...
If you're looking to compare objects for equality, serializing them and then comparing is pointless when you can simply override the class' equals method and compare them by their fields (there will undoubtedly be cases where certain fields of the class should not be taken into account, and your method of serialization may not offer that).
Adding "equal" method to each class takes weeks.
I'm sure this isn't the case. Modern IDEs are able to generate these methods for you, and libraries (such as Guava) offer methods that can compare objects by their fields in a single line of code.
You might want to give Apache's EqualsBuilder a try, most specifically this method (and variances of it); I think in the latest versions (3.7) it is fully recursive, but I think they also have a bug with Strings only solved in the yet-to-be-released v3.8, checking transient fields is also an option of some of the methods.
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.
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.
From javadocs
When an object is serialized, information that identifies its class is recorded in
the serialized stream. However, the class's definition ("class file") itself is
not recorded. It is the responsibility of the system that is deserializing the
object to determine how to locate and load the necessary class files.
De-serialization will require the .class file to create the object from the serialized stream. As the serialized object does not contain the class definition, so there is no way to extract the object out of the stream without having the .class file.