equals vs Arrays.equals in Java equals vs Arrays.equals in Java java java

equals vs Arrays.equals in Java


array1.equals(array2) is the same as array1 == array2, i.e. is it the same array. As @alf points out it's not what most people expect.

Arrays.equals(array1, array2) compares the contents of the arrays.


Similarly array.toString() may not be very useful and you need to use Arrays.toString(array).


It's an infamous problem: .equals() for arrays is badly broken, just don't use it, ever.

That said, it's not "broken" as in "someone has done it in a really wrong way" — it's just doing what's defined and not what's usually expected. So for purists: it's perfectly fine, and that also means, don't use it, ever.

Now the expected behaviour for equals is to compare data. The default behaviour is to compare the identity, as Object does not have any data (for purists: yes it has, but it's not the point); assumption is, if you need equals in subclasses, you'll implement it. In arrays, there's no implementation for you, so you're not supposed to use it.

So the difference is, Arrays.equals(array1, array2) works as you would expect (i.e. compares content), array1.equals(array2) falls back to Object.equals implementation, which in turn compares identity, and thus better replaced by == (for purists: yes I know about null).

Problem is, even Arrays.equals(array1, array2) will bite you hard if elements of array do not implement equals properly. It's a very naive statement, I know, but there's a very important less-than-obvious case: consider a 2D array.

2D array in Java is an array of arrays, and arrays' equals is broken (or useless if you prefer), so Arrays.equals(array1, array2) will not work as you expect on 2D arrays.

Hope that helps.


Look inside the implementation of the two methods to understand them deeply:

array1.equals(array2);
/** * Indicates whether some other object is "equal to" this one. * <p> * The {@code equals} method implements an equivalence relation * on non-null object references: * <ul> * <li>It is <i>reflexive</i>: for any non-null reference value *     {@code x}, {@code x.equals(x)} should return *     {@code true}. * <li>It is <i>symmetric</i>: for any non-null reference values *     {@code x} and {@code y}, {@code x.equals(y)} *     should return {@code true} if and only if *     {@code y.equals(x)} returns {@code true}. * <li>It is <i>transitive</i>: for any non-null reference values *     {@code x}, {@code y}, and {@code z}, if *     {@code x.equals(y)} returns {@code true} and *     {@code y.equals(z)} returns {@code true}, then *     {@code x.equals(z)} should return {@code true}. * <li>It is <i>consistent</i>: for any non-null reference values *     {@code x} and {@code y}, multiple invocations of *     {@code x.equals(y)} consistently return {@code true} *     or consistently return {@code false}, provided no *     information used in {@code equals} comparisons on the *     objects is modified. * <li>For any non-null reference value {@code x}, *     {@code x.equals(null)} should return {@code false}. * </ul> * <p> * The {@code equals} method for class {@code Object} implements * the most discriminating possible equivalence relation on objects; * that is, for any non-null reference values {@code x} and * {@code y}, this method returns {@code true} if and only * if {@code x} and {@code y} refer to the same object * ({@code x == y} has the value {@code true}). * <p> * Note that it is generally necessary to override the {@code hashCode} * method whenever this method is overridden, so as to maintain the * general contract for the {@code hashCode} method, which states * that equal objects must have equal hash codes. * * @param   obj   the reference object with which to compare. * @return  {@code true} if this object is the same as the obj *          argument; {@code false} otherwise. * @see     #hashCode() * @see     java.util.HashMap */public boolean equals(Object obj) {    return (this == obj);}

while:

Arrays.equals(array1, array2);
/** * Returns <tt>true</tt> if the two specified arrays of Objects are * <i>equal</i> 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 <tt>e1</tt> * and <tt>e2</tt> are considered <i>equal</i> if <tt>(e1==null ? e2==null * : e1.equals(e2))</tt>.  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 <tt>null</tt>.<p> * * @param a one array to be tested for equality * @param a2 the other array to be tested for equality * @return <tt>true</tt> if the two arrays are equal */public static boolean equals(Object[] a, Object[] a2) {    if (a==a2)        return true;    if (a==null || a2==null)        return false;    int length = a.length;    if (a2.length != length)        return false;    for (int i=0; i<length; i++) {        Object o1 = a[i];        Object o2 = a2[i];        if (!(o1==null ? o2==null : o1.equals(o2)))            return false;    }    return true;}