Your's Deeply - Why Arrays.deepEquals When We Have Arrays.equals
While everybody would naturally accept the following lines of code on grounds of reference equality and value equality and that String and wrappers override the equals method, it takes some effort at first to accept the behavior of Arrays.equals and Arrays.deepEquals
So, it just loops through the given arrays, does a equals on each of the pairs. This means that if you are passing in a String/Wrapper array or any other arrays whose equals method is overridden, then they are equal. Non-equals-overridden classes (derived from Object) will return false.
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
Arrays.deepEquals
12345678910111213141516171819202122232425
for(inti=0;i<length;i++){Objecte1=a1[i];Objecte2=a2[i];if(e1==e2)continue;if(e1==null)returnfalse;// Figure out whether the two elements are equalbooleaneq;if(e1instanceofObject[]&&e2instanceofObject[])eq=deepEquals((Object[])e1,(Object[])e2);elseif(e1instanceofbyte[]&&e2instanceofbyte[])eq=equals((byte[])e1,(byte[])e2);……elseeq=e1.equals(e2);if(!eq)returnfalse;}returntrue;
Now, the Awesome stuff !!
Equals not overridden (nested and non-nested)
While doing an Arrays.equals for nested or non-nested ‘non-overridden equals’ objects, it is safe to assume that if Arrays.equals return false, then Arrays.deepEquals also return false.
While doing an Arrays.equals for non-nested ‘overridden equals’ objects, it can be said that if Arrays.equals is true, then Arrays.deepEquals also return true.
since they are just one-to-one equals call on each pair.
Nested
Interesting scenario : While doing an Arrays.equals for nested ‘overridden equals’ objects, if Arrays.equals is false, then Arrays.deepEquals need not be false.
Consider two Object arrays which has two values - a String and a String array
The result for Arrays.deepEquals is logical since each (from the source), the method loops through each pair of elements, checks whether it is an array type and calls deepEquals on each of the pair. If it is an non-array type, then it just calls the equals on the object.
However, the result of Arrays.equals is tricky but at the same time obvious. The Arrays.equals method blindly calls equals on each pair and since the second arguments String[] are of Object type (whose equals is not overridden), it checks for reference equality and fails !!