Meaning of Objects.deepEquals method - java

The question is about static methods Objects.deepEquals class (since Java 7):
public static boolean deepEquals(Object a, Object b) {
if (a == b)
return true;
else if (a == null || b == null)
return false;
else
return Arrays.deepEquals0(a, b);
}
As it said in javadoc of this method:
Returns true if the arguments are deeply equal to each other and false
otherwise.
What I do not understand: where is the depth of comparison? As we can see inside its implementation it just does references comparison, and inside Arrays.deepEquals0(a, b) for simple Object and Object arguments it invokes
just: eq = e1.equals(e2);. So in what kind of sense two objects are deeply equal?

The comparison would be deep, if you passed Array objects.
Non-array objects will not be evaluated deeper than what you get with equals .
So the depth isn't relevant in your case :
Two null values are deeply equal. If both arguments are arrays, the
algorithm in Arrays.deepEquals is used to determine equality.
Otherwise, equality is determined by using the equals method of the
first argument.
Quoted from :
Object.deepEquals

You can refer: Your's Deeply - Why Arrays.deepEquals When We Have Arrays.equals
Arrays.deepEquals looks really deep
From the source, we could understand that Arrays.deepEquals
Loops through the input arrays, gets each pair
Analyses the type of each pair
Delegates the equal deciding logic to one of the overloaded
Arrays.equals if they are one of the primitive arrays
Delegates recursively to Arrays.deepEquals if it is an Object array
Calls the respective object’s equals, for any other object

Related

Objects.equals and Object.equals

I try to create a tuple class that allows a tuple-like structure in Java. The general type for two elements in tuple are X and Y respectively. I try to override a correct equals for this class.
Thing is, I know Object.equals falls into default that it still compares based on references like "==", so I am not so sure I can use that. I looked into Objects and there is an equals() in it. Does this one still compare on references, or it compares on contents?
Quickly imagined the return statement as something like:
return Objects.equals(compared.prev, this.prev) && Objects.equals(compared.next, this.next);
where prev and next are elements of tuple. Would this work?
The difference is the Objects.equals() considers two nulls to be "equal". The pseudo code is:
if both parameters are null or the same object, return true
if the first parameter is null return false
return the result of passing the second parameter to the equals() method of the first parameter
This means it is "null safe" (non null safe implementation of the first parameter’s equals() method notwithstanding).
this is literal code from java source: as you can see, #Agent_L is right
The answer to your question "Does this one [Objects.equals] still compare on references, or it compares on contents?" - Objects.equals does some comparisons on the references but it expects the first argument's class to implement equals() in which the comparison of contents is done as well as on reference.
Your second question about the implementation of equals in your tupple-like class having prev and next as its tupple attributes the answer is: your suggested implementation would work only if
prev and next are primitives or if their type implements equals properly.
So if prev for example is of type Foo, then you can use Objects.equals to test the two Foo's only if class Foo implements equals as expected.
Objects.equals just calls it's first arguments .equals method. In java, if you want to be able to test for equality in instances of a class you made, then you have to override the equals method. instance.equals() only uses == if that instances type doesn't override the equals method.

difference between a.equals(b) and array.equals(a,b) [duplicate]

This question already has answers here:
equals vs Arrays.equals in Java
(9 answers)
Closed 7 years ago.
I have run this small program:
String[] a = {"a","b"};
String[] b = {"a","b"};
if (a.equals(b)){
System.out.println("woop");
}else{
System.out.println("doh!");
}
if (Arrays.equals(a, b)){
System.out.println("woop");
}else{
System.out.println("doh!");
}
The output of the program is "doh! woop".
I get the difference between the == and .equals but what is the difference between these equals operations?
TL;DR
equals compares array instances, Arrays.equals compares array elements.
Full Explanation
Arrays do not implement equals. As a result, they hand the method off to Object which is implemented as follows.
public boolean equals(Object obj) {
return (this == obj);
}
Thus, equals on an array is the same as ==.
Arrays.equals has the following description. It compares the elements of the array.
Returns true if the two specified arrays of longs are equal to one another. Two arrays are considered equal if both arrays contain the same number of elements, and all corresponding pairs of elements in the two arrays are equal. In other words, two arrays are equal if they contain the same elements in the same order. Also, two array references are considered equal if both are null.
Arrays.equals(Object[] a, Object[] a2)...
returns true if the two specified arrays of Objects are equal to one another. The two arrays are considered equal if both arrays contain the same number of elements, and all corresponding pairs of elements in the two arrays are equal. Two objects e1 and e2 are considered equal if (e1==null ? e2==null : e1.equals(e2)). In other words, the two arrays are equal if they contain the same elements in the same order. Also, two array references are considered equal if both are null.
In short, all your Strings are compared through equals.
See API.
Object.equals, which is invoked when comparing two arrays with the array1.equals(array2) idiom, compares the reference, just like ==.
See source for java.lang.Object:
public boolean equals (Object o) {
return this == o;
}
The difference is that a.equals(b) will use == under the hood, since arrays don't override the Object.equals() method. You use this to test for instance equality between arrays.
So in your case, a.equals(b) will return false, since the two arrays are different instances.
Instead, Arrays.equals() actually compares what's inside the arrays. If the arrays contain the same values, then Arrays.equals() returns true. You use this to test for semantic equality between arrays.
With arrays, a.equals(b) is the same as a == b. This is checking if the two array instances are the same. Arrays.equals(a,b) takes the time to compare each element of both arrays and checks if the elements are equal, which is different than checking if the containers themselves are equal.
A quick analogy: Let's say a and b are buckets. Asking if the two buckets are the same is not the same as asking if what is in the buckets is the same.

Does it matter if two hashCodes are equal, even if the two objects aren't from the same type?

Let's say I have two types A and B that both have a unique id field, here is how I usually implement the equals() and hashCode() methods:
#Override
public boolean equals(Object obj) {
return obj instanceof ThisType && obj.hashCode() == hashCode();
}
#Override
public int hashCode() {
return Arrays.hashCode(new Object[] { id });
}
In that case, given that A and B both have a 1-arg constructor to set their respective id field,
new A(1).equals(new A(1)) // prints true as expected,
new A(1).equals(new A(2)) // prints false as expected,
new A(1).equals(new B(1)) // prints false as expected.
But also,
new A(1).hashCode() == new B(1).hashCode() // prints true.
I wonder if it matters if two hashCodes are equal, even if the two objects aren't from the same type? Could hashCode() be used somewhere else than in equals()? If yes, to what purpose?
I thought about implementing the two methods as follow:
#Override
public boolean equals(Object obj) {
return obj != null && obj.hashCode() == hashCode();
}
#Override
public int hashCode() {
return Arrays.hashCode(new Object[] { getClass(), id });
}
Adding the class to the hashCode generation would solve this potential problem. What do you think? Is it necessary?
For objects of different classes the same hashCode() does not matter. The hashCode() only says that the objects are possibly the same. If e.g. HashSet encounters the same hashCode() it will test for equality with equals().
The rule is simple:
A.equals(B) implies B.hashcode() == A.hashcode()
B.hashcode() != A.hashcode() implies !A.equals(B)
There should be no other relations between the two. If you use hashcode() inside equals(), you should have a warning.
Hashcode is definitely not used in equals; it is used by collections based on the data structure called a hash table. It is always OK from the correctness standpoint for two hashcodes to equal each other; this is called a hash collision, it is unavoidable in the general case, and the only consequence is weaker performance.
Nothing wrong with two different objects (even of the same type) to have the equal hash code, but your second variant of equals() looks odd to me. It will work only if you can guarantee that your objects will be compared only to the objects of the same type.
Could hashCode() be used somewhere else than in equals()?
This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable. from javadoc
Also
The general contract of hashCode is:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.
Not that, when A extends B, or B extends A, then your equals method is faulty, since:
a.equals(b) != b.equals(a)
if a and b happen to have the same hash code.

in which cases equals() is similar to ==? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Difference Between Equals and ==
in which cases equals() works exactly like == operator?
It seems that they both act similar for primitive data types. Are there any other cases in which both of them act equal?
== compares the bits of reference for Object type so if you have reference to same Object it would be the case
For example
Integer for value -128 and 127 (inclusive) it caches (while autoboxing) the instance so it would be the case here for the mentioned range of value of Integer
For primitive data types, there is no equals() (because they are not objects, and have no methods).
The default implementation (in class Object) for equals() just does object identity check (i.e. the same as ==). So if a class does not override it, it will have the same result as ==.
The operator == will always compare references for objects, and the actual value for primitive types.
Note that an array of primitives like int[] is still an object!
String test1 ="test";
String test2 = test1;
System.out.println(test1 == test2);
System.out.println(test1.equals(test2));
Both will print -
true
true
In addition to primitives (which are a special case) == and equals() behave similarly for every case in which reference equality is the same as actual equality:
Interned Strings
Certain Integer references (normally between -128 and +127, but this is configurable, and it depends on how the instance was constructed)
Singletons
Instances of Object (and any other class that doesn't override equals())
Obviously, when in doubt, use equals()
The equals() method evaluates on hashCode comparisons. While == compares objects by reference.

Question about arrays in Java

Can someone explain why, A.equals(B) is false, when I initiate B using int[] B = A.clone() BUT true if I initiate B using int[] B = A?
int[] A = {1, 2, 3, 4, 5};
int[] B = A;
//int[] B = A.clone();
if(A==B){//true
System.out.println("Equal");
}
if(A.equals(B)){//true
System.out.println("Equal");
}
Apparently, equals method for arrays in Java is comparing reference equality (same as ==).
If you clone it, you have a reference different object - the clone array. But, if you just point another reference to it it's the same.
Well if you use
int[] B = A;
then B and A refer to the same object, so trivially they're equal. The first comparison (==) would certainly return false between A and A.clone() as the values refer to different objects. It sounds like arrays don't override equals (e.g. as ArrayList does), hence the clone not being equal to the original under the equals method either.
EDIT: Indeed, from the language specification section 10.7, Array Members:
All the members inherited from class Object; the only method of Object that is not inherited is its clone method.
In other words, the array overrides clone() but not toString / hashCode / equals.
For comparing arrays in Java, you might want to try
java.util.Arrays.equals(a,b);
If you use a == b they should be different- this compares their memory references.
If you use a.equals(b), it probably inherits from Object, which simply uses ==.
That probably explains why they made Arrays.equals() in the first place. Now why they chose a.equals(b) to not compare elements... hard to say.
Your question is answered precisely by the Javadoc for clone():
http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#clone%28%29
specifically:
[ The clone() method ] Creates and
returns a copy of this object. The
precise meaning of "copy" may depend
on the class of the object. The
general intent is that, for any object
x, the expression:
x.clone() != x
will be true, and that the expression:
x.clone().getClass() == x.getClass()
will be true, but these are not
absolute requirements. While it is
typically the case that:
x.clone().equals(x)
will be true, this is not an absolute
requirement.
int[] B = A;
Makes B point to the same object in memory as A, so not only are they equal, they are the same.
when you assign B = A, you assign the reference to the same object. With clone() you get a copy of the object. The equality operator (==) tests if both symbols reference the same object where .equals method checks if the two objects have the same value (defined by the implementation of the class)

Categories

Resources