How to compare the data of two same Objects in Java - java

I have a class
MyData
and its object
myData
In that Class MyData .. there are multiple fields
like
int id
String name
String desc
etc ..
Now i have two objects of this class ..
Is it possible to check that if the data of these two object are all the same , Like both objects have the same Id ,same Name ,same Desc ... Without checking each and every field of this object ..(i.e without checking the id,name,desc of Each object myself) As there are dozens of fields of this object .
I am using JAVA with GWT
Some implementation i came across.. Not sure if this is some thing possible .valid
private static String oldSequence = "";
boolean changed(TestSequence sequence) {
String newSequence = serializeToString(sequence);
boolean changed = !newSequence.equals(oldSequence);
oldSequence = newSequence;
return changed;
}
private static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(b);
o.writeObject(obj);
return b.toByteArray();
}
private static String serializeToString(Object obj) {
try {
return new String(serialize(obj));
} catch (Exception ex) {
return "" + ex;
}
}
Thanks

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.

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();
}
...

GWT doesn't make a difference to your requirement.
There is no direct way.
You have to define your equality to check weather they are equal or not. That is overriding equals() method.
#Override
public boolean equals(Object obj) { ...
Before doing:Right way to implement equals contract

Like everyone else is saying, you should override the equals() and hashCode() methods.
Note that you don't have to do this manually. In Eclipse you can simply click on Source/generate hashCode() and equals() and it will do the work for you. I am sure other IDEs have similar feature as well.

If you don't want to add any more code when you add a new field, you can try iterating over fields.
You said "Without checking each and every field of this object ..(i.e without checking the id,name,desc of Each object myself) ", I couldn't figure out whether you don't want to check for each field for equality, or don't want to WRITE a check for each field for equality. I assumed the latter since you tried to add an equality comparison method by using bytewise checks.
Anyways, the code to check each field follows. You can copy/paste to any object. If, in the future, you want some fields to be checked and some not, you can use annotations.
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyData myData = (MyData) o;
Field[] fields = this.getClass().getDeclaredFields();
for(Field field:fields){
Object o1 = null;
Object o2 = null;
try {
o1 = field.get(this);
o2 = field.get(o);
} catch (IllegalAccessException e) {
return false;
}
if(o1 == null && o2 != null) return false;
if(o2 == null && o1 != null) return false;
if(o2 == null && o1 == null) continue;
if(!o2.equals(o1)) return false;
}
return true;
}

No.
You have to override the equals() method and compare the objects in that.

Override the equals method of the object in MyData and check the fields independently.

Serialize your objects and compare the results!
You just should be wise in selection of your serialization method.

Override hashCode() and equals() methods
hashCode()
This method provides the has code of an object.
Basically the default implementation of hashCode() provided by Object is derived by mapping the memory address to an integer value. If look into the source of Object class , you will find the following code for the hashCode.
public native int hashCode();
It indicates that hashCode is the native implementation which provides the memory address to a certain extent. However it is possible to override the hashCode method in your implementation class.
equals()
This method is used to make equal comparison between two objects. There are two types of comparisons in Java. One is using “= =” operator and another is “equals()”. I hope that you know the difference between this two. More specifically the .equals() refers to equivalence relations. So in broad sense you say that two objects are equivalent they satisfy the equals() condition.

Related

How to correctly implement equals(), hashCode() if the values are within a range of each other?

The criteria is that equals() method where the objects are considered equal if the value of the double variable is within +/- 10 of the other object's value of the double variable.
I'm not sure how to correctly implement hashCode() so that the hashCode would be equal if it satisfies the conditions of the equals() method.
I would really appreciate your input! Thanks!
public class Test
{
private double value;
private boolean isEqualValues (final double valueOne, final double valueTwo)
{
if(valueOne == valueTwo)
{
return true;
}
else if((valueOne - valueTwo <= 10) &&
(valueOne - valueTwo >= -10))
{
return true;
}
else
{
return false;
}
#Override
public boolean equals(final Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
Test test = (Test) o;
if(isEqualValues(test.value, value))
{
return true;
}
else
{
return false;
}
}
//How to implement hashCode()
#Override
public int hashCode()
{
//unsure how to correctly implement hashCode() so that the hashCode would be equal if it
//satisfies the conditions of the equals() method above
}
}
There's no way to consistently implement this, since equals() demands transitivity:
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
new Test(1), new Test(9) and new Test(14) would fail that test (assuming a trivial one-argument constructor that assigns its argument to value).
One way to work around that is to not check for the absolute distance, but "categorize" your objects using some formula, for example take the floor of value / 10 and compare that.
This way some "close" values like new Test(9) and new Test(11) would compare as not-equal, but other than that you'd get a similar result to what you described.
private long getEquivalenceGroup() {
return Math.floorDiv((long) value, 10);
}
#Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Test test = (Test) o;
return test.getEquivalenceGroup() == this.getEquivalenceGroup();
}
#Override
public int hashCode()
{
return Long.hashCode(getEquivalenceGroup());
}
As long as getEquivalenceGroup() is implemented in a stable manner this will produce "groups" of slightly different objects that still compare as equal and has a valid hashCode() implementation.
Note: if you want a comparison as described in the question but you don't necessarily need it to be returned by equals() then adding a boolean isClose(Test other) is perfectly fine. The only problem is you are trying to implement the equals method specifically with that semantic.
You can't and you shouldn't.
You should implement a comparator and do such operations using that.

The java right implemantion of equals?

i try to find out what is the right way to implement java equals.
reading on the net I saw that there are many Thoughts on the subject I narrow down to 2 options
1 using instance of and on using getClass() != obj.getClass()
to follow the rules of :
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object)
this is my final result :
public class Foo {
private List<Long> days;
private String project;
public boolean equals(Object obj) {
if (this == obj)
return true;
//avoid symmetry problem
if (obj == null || getClass() != obj.getClass())
return false;
Foo test = (Foo)obj;
return equals(this.project,test.project) && equals(this.days,test.days);
}
public static boolean equals(Object a,Object b) {
return a == b || a != null && b!=null && a.equals(b);
}
}
what do you say ?
Your code looks good in general. getClass() != obj.getClass() is sufficient enough. It will only fail for positive scenario if someone goes crazy with tricky custom code to load same class with different classloaders.
I would also replace your custom equals on fields with standard Objects.equals at the end:
return Objects.equals(days, foo.days) &&
Objects.equals(project, foo.project);
It's always good to override hashcode when you override equals too.
You may want to custom the equals on the list if the order matter.
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Foo foo = (Foo) o;
return Objects.equals(days, foo.days) && Objects.equals(project, foo.project);
}
#Override
public int hashCode() {
return Objects.hash(days, project);
}
You would rewrite your code with the following consideration, we use equals() to compare objects otherwise, = sign used to compare data types

Not able to return false in equals() method when object o is null. I have added my equals() implementation as well the test case

My equals() method:
Here when in second if statement when my my object is null for example, I should return false but for some reason my code fails to do so. Any help?
public boolean equals(Prof o) {
boolean res = false;
if(this == o) {
res = true;
}
if(o == null || this.getClass() != o.getClass()) {
res = false;
}
Prof other = (Prof) o;
if(this.year == other.year) {
if(this.id.equals(other.id)) {
res = true;
}
}
else {
res = false;
}
return res;
}
Test Case:
public void test02_ProfEqualHash() {
Prof p1 = new Prof("John S Lee", "yu213", 5);
assertTrue(p1.equals(p1));
Prof p0 = null; // null
assertFalse(p1.equals(p0)); // my equals() implementation fails here
Date d = new Date();
String s = "Hello";
assertFalse(p1.equals(d));
assertFalse(p1.equals(s));
Prof p2 = new Prof("John L", "yu213", 5);
assertTrue(p1.equals(p2));
assertTrue(p1.hashCode() == p2.hashCode());
assertTrue(p2.equals(p1));
Prof p3 = new Prof("John S Lee", "yu203", 5);
assertFalse(p1.equals(p3));
//assertNotEquals(p1.hashCode(), p3.hashCode());
Prof p4 = new Prof("Tracy T", "yu053", 2);
assertFalse(p1.equals(p4));
//assertNotEquals(p1.hashCode(), p4.hashCode());
Prof p5 = new Prof("John S Lee", "yu213", 8);
assertFalse(p1.equals(p5));
//assertTrue(p1.hashCode() != p5.hashCode());
}
First of all, in order to correctly override Object's equals(), the method signature should be:
public boolean equals(Object o) {
....
}
Even though your test code calls your equals() method, JDK classes that expect Object's equals() signature will not.
In addition, you should return false immediately when you find that the o argument is null, in order not to access it later in your method (which would cause NullPointerException).
A correct implementation can look like this:
public boolean equals (Object o)
{
if (this == o) {
return true;
}
if (o == null || !(o instanceof Prof)) {
return false;
}
Prof other = (Prof) o;
return this.year == other.year && this.id.equals(other.id);
}
In Java Object class is the superclass of every class. So in order to override the equal method defined in the Object class, you need to follow the same method definition, which is:
#Override
public boolean equals(Object other) {
// here goes your implementation class
}
Since your definition of equals has Prof as an argument, hence you are not actually overriding the Object equals method.
For more information on the equals contract, you can read Item10 from Effective Java book by Josh Bloch.
Also, if your class has an equals method, then you should always define the hashCode implementation as well. Here is the implementation of this method:
#Override
public int hashCode() {
return Objects.hash(year, id);
}

issue with overriding .equals() method

I was working on overriding .equals() in java for an "Item" class with a Constructor in the form of:
public Item(final String theName, final BigDecimal thePrice, final int theBulkQuantity,
final BigDecimal theBulkPrice) {
myName = Objects.requireNonNull(theName);
myPrice = Objects.requireNonNull(thePrice);
myBulkQuantity = theBulkQuantity;
myBulkPrice = theBulkPrice;
}
using this .equals method:
#Override
public boolean equals(final Object theOther) {
boolean result = false;
if (this == theOther) {
result = true;
}
else if (theOther != null && theOther == this.getClass()) {
final Item other = (Item) theOther;
if ((this.myName.equals(other.myName))
&& (this.myBulkQuantity == other.myBulkQuantity)
&& (this.myPrice.equals(other.myPrice))
&& (this.myBulkPrice.equals(other.myBulkPrice))) {
result = true;
}
}
return result;
}
I'm a new Computer Science student and this is my first attempt at overriding. I would have overlooked this if I had not used JUnit testing using the following:
testItemB = new Item("ItemB", new BigDecimal("5.00"), 5, new BigDecimal("20.00"));
testItemC = new Item("ItemB", new BigDecimal("5.00"), 5, new BigDecimal("20.00"));
and got an assertion error saying that they weren't equivalent. At first glance I am pretty sure that I got everything but do you guys happen to see anything glaring?
In the equals() method you compared the object instance theOther with this.getClass() which will always return false since your are comparing an instance with a class type.
Depending on your use case, you may use
obj1.getClass().equals(obj2.getClass())
or
theOther instanceof Item

getting an object from an arrayList with objects attribute

I have 2 classes.
public class klass1 {
String bir;
String myID;
klass1(String bir, String myID)
{
this.bir=bir;
this.myID=myID;
}
}
.
import java.util.*;
public class dd {
public static void main(String[] args) {
ArrayList<Object> ar=new ArrayList();
ar.add(new klass1("wer","32"));
ar.add(new klass1("das","23"));
ar.add(new klass1("vz","45"));
ar.add(new klass1("yte","12"));
ar.add(new klass1("rwwer","43"));
ar.remove(new klass1("vz","45"));//it's not worked!!!
System.out.println(ar.size());
}
}
What I want is removing or getting an object from array list with object's second attribute. How can I do that? Is there an easy way for it?
Just implement the equals method in the class Klass1.
public class Klass1 {
String bir;
String myID;
Klass1(String bir, String myID)
{
this.bir=bir;
this.myID=myID;
}
public boolean equals(Object o){
if(o instanceof Klass1)
return ((Klass1)o).myID.equals(myID);
else
return false;
}
}
Its because you are trying to delete a new object which isnt in the arraylist. When you use new klass1("vz","45") you are creating a new instance of this class which isnt in the arraylist.
What the system does internally is to compare those classes using equals. Why this doesn't work is explained in the following code:
Object o1 = new Object();
Object o2 = new Object();
System.out.println(o1 == o2); // false, obviously
System.out.println(o1.equals(o2)); // false
System.out.println(o1); // java.lang.Object#17046822
System.out.println(o2); // java.lang.Object#22509bfc
You can tell by the number following the # that these objects have a different hash values, and this is what the equals function of Object does check.
This is relevant for your klass, because unless you overwrite equals, you will use the equals of Object. And if you implement equals you should always implement hashcode as well. Because both tell you something about whether or not two objects are the "same", and if the one says something else than the other, some part of your code might get confused.
How to properly implement equals for your class:
#Override
public int hashCode() {
int hash = 7;
hash = 17 * hash + Objects.hashCode(this.bir);
hash = 17 * hash + Objects.hashCode(this.myID);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final klass1 other = (klass1) obj;
if (!Objects.equals(this.bir, other.bir)) {
return false;
}
if (!Objects.equals(this.myID, other.myID)) {
return false;
}
return true;
}
This can be done in most IDEs btw with a shortcut (i.E. alt-insert in Netbeans). Note that I did this in Java 7 using Objects. If you are in Java 6, you need to manually type(a == b) || (a != null && a.equals(b)); with the appropriate objects to compare.
Creating a proper hashcode is not always trivial, for more complex objects you might want to read a bit about hashcodes first. For simple objects: multiply primes with something.
The equals method is usually trivial, it is just important to first check for null and for class equality. This is often forgotten by programmers and a common source for NullPointerExceptions and ClassCastExceptions.

Categories