Java 中的 equals 与 Arrays.equals

发布于 2024-12-25 16:07:08 字数 158 浏览 1 评论 0原文

在Java中比较数组时,以下两条语句有什么区别吗?

Object[] array1, array2;
array1.equals(array2);
Arrays.equals(array1, array2);

如果是的话,它们是什么?

When comparing arrays in Java, are there any differences between the following 2 statements?

Object[] array1, array2;
array1.equals(array2);
Arrays.equals(array1, array2);

And if so, what are they?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

小情绪 2025-01-01 16:07:08

array1.equals(array2)array1 == array2 相同,即是否是同一个数组。 正如 @alf 指出的,这并不是大多数人所期望的。

Arrays.equals(array1, array2) 比较数组的内容。


同样,array.toString()可能不是很有用,您需要使用Arrays.toString(array)

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).

百合的盛世恋 2025-01-01 16:07:08

这是一个臭名昭著的问题:数组的 .equals() 已严重损坏,永远不要使用它。

也就是说,它并不像“有人以一种非常错误的方式做到了”那样“被破坏”——它只是做了定义的事情,而不是通常期望的事情。因此,对于纯粹主义者来说:这完全没问题,这也意味着,永远不要使用它。

现在,equals 的预期行为是比较数据。默认行为是比较身份,因为 Object 没有任何数据(对于纯粹主义者:是的,它有,但这不是重点);假设是,如果您在子类中需要equals,您将实现它。在数组中,没有适合您的实现,因此您不应该使用它。

所以区别在于,Arrays.equals(array1, array2) 的工作方式如您所期望的(即比较内容),array1.equals(array2) 退回到 Object.equals 实现,它反过来比较身份,因此更好地用 == 代替(对于纯粹主义者:是的,我知道 null)。

问题是,如果数组元素没有正确实现equals,即使Arrays.equals(array1, array2)也会给你带来很大的麻烦。我知道这是一个非常幼稚的说法,但是有一个非常重要的不太明显的情况:考虑一个二维数组。

Java 中的二维数组是数组的数组,而数组的 equals 已损坏(或者如果您愿意,则无​​用),因此 Arrays.equals(array1, array2) 将不起作用正如您对二维数组的期望。

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.

长伴 2025-01-01 16:07:08

查看这两个方法的实现内部以深入理解它们:

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;
}

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;
}
屌丝范 2025-01-01 16:07:08

叹。早在 70 年代,我是 IBM 370 系统的“系统程序员”(系统管理员),我的雇主是 IBM 用户组 SHARE 的成员。有时会发生这样的情况:有人针对某些 CMS 命令的某些意外行为提交了 APAR(错误报告),IBM 会回复 NOTABUG:该命令执行其设计目的(以及文档中所述的内容)。

SHARE想出了一个反驳办法:BAD——Broken As Design。我认为这可能适用于数组的 equals 实现。

Object.equals 的实现没有任何问题。对象没有数据成员,因此没有什么可比较的。两个“对象”相等当且仅当它们实际上是同一个对象(内部具有相同的地址和长度)。

但这种逻辑不适用于数组。数组有数据,并且您期望通过比较(通过 equals)来比较数据。理想情况下,是 Arrays.deepEquals 的方式,但至少是 Arrays.equals 的方式(元素的浅比较)。

所以问题是数组(作为内置对象)不会覆盖 Object.equals。 String(作为命名类)确实覆盖 Object.equals 并给出您期望的结果。

给出的其他答案是正确的: [...].equals([....]) 只是比较指针而不是内容。也许有一天有人会纠正这个问题。或者也许不是:如果 [...].equals 实际比较元素,有多少现有程序会崩溃?我怀疑数量不多,但超过零。

Sigh. Back in the 70s I was the "system programmer" (sysadmin) for an IBM 370 system, and my employer was a member of the IBM users group SHARE. It would sometimes happen thatsomebody submitted an APAR (bug report) on some unexpected behavior of some CMS command, and IBM would respond NOTABUG: the command does what it was designed to do (and what the documentation says).

SHARE came up with a counter to this: BAD -- Broken As Designed. I think this might apply to this implementation of equals for arrays.

There's nothing wrong with the implementation of Object.equals. Object has no data members, so there is nothing to compare. Two "Object"s are equal if and only if they are, in fact, the same Object (internally, the same address and length).

But that logic doesn't apply to arrays. Arrays have data, and you expect comparison (via equals) to compare the data. Ideally, the way Arrays.deepEquals does, but at least the way Arrays.equals does (shallow comparison of the elements).

So the problem is that array (as a built-in object) does not override Object.equals. String (as a named class) does override Object.equals and give the result you expect.

Other answers given are correct: [...].equals([....]) simply compares the pointers and not the contents. Maybe someday somebody will correct this. Or maybe not: how many existing programs would break if [...].equals actually compared the elements? Not many, I suspect, but more than zero.

原来分手还会想你 2025-01-01 16:07:08

数组从 Object 继承 equals(),因此只有在将数组与自身进行比较时,compare 才会返回 true。

另一方面,Arrays.equals 比较数组的元素。

此代码片段阐明了差异:

Object o1 = new Object();
Object o2 = new Object();
Object[] a1 = { o1, o2 };
Object[] a2 = { o1, o2 };
System.out.println(a1.equals(a2)); // prints false
System.out.println(Arrays.equals(a1, a2)); // prints true

另请参阅 Arrays.equals()。另一个静态方法可能也令人感兴趣: Arrays.deepEquals()

Arrays inherit equals() from Object and hence compare only returns true if comparing an array against itself.

On the other hand, Arrays.equals compares the elements of the arrays.

This snippet elucidates the difference:

Object o1 = new Object();
Object o2 = new Object();
Object[] a1 = { o1, o2 };
Object[] a2 = { o1, o2 };
System.out.println(a1.equals(a2)); // prints false
System.out.println(Arrays.equals(a1, a2)); // prints true

See also Arrays.equals(). Another static method there may also be of interest: Arrays.deepEquals().

听你说爱我 2025-01-01 16:07:08

数组的equals()是从Object继承的,所以它不看数组的内容,它只认为每个数组都等于它自己。

Arrays.equals() 方法do比较数组的内容。所有基本类型都有重载,而对象的重载则使用对象自己的 equals() 方法。

The equals() of arrays is inherited from Object, so it does not look at the contents of the arrrays, it only considers each array equal to itself.

The Arrays.equals() methods do compare the arrays' contents. There's overloads for all primitive types, and the one for objects uses the objects' own equals() methods.

寻梦旅人 2025-01-01 16:07:08

Arrays.equals(array1, array2) :

检查两个数组是否包含相同数量的元素,以及两个数组中所有对应的元素对是否相等。

array1.equals(array2)

将对象与另一个对象进行比较,仅当两个对象的引用相等时才返回 true,如 Object.equals() 中所示

The Arrays.equals(array1, array2) :

check if both arrays contain the same number of elements, and all corresponding pairs of elements in the two arrays are equal.

The array1.equals(array2) :

compare the object to another object and return true only if the reference of the two object are equal as in the Object.equals()

橘香 2025-01-01 16:07:08
import java.util.Arrays;
public class ArrayDemo {
   public static void main(String[] args) {
   // initializing three object arrays
   Object[] array1 = new Object[] { 1, 123 };
   Object[] array2 = new Object[] { 1, 123, 22, 4 };
   Object[] array3 = new Object[] { 1, 123 };

   // comparing array1 and array2
   boolean retval=Arrays.equals(array1, array2);
   System.out.println("array1 and array2 equal: " + retval);
   System.out.println("array1 and array2 equal: " + array1.equals(array2));

   // comparing array1 and array3
   boolean retval2=Arrays.equals(array1, array3);
   System.out.println("array1 and array3 equal: " + retval2);
   System.out.println("array1 and array3 equal: " + array1.equals(array3));

   }
}

这是输出:

    array1 and array2 equal: false
    array1 and array2 equal: false

    array1 and array3 equal: true
    array1 and array3 equal: false

看到这种问题,我个人会根据您的问题使用 Arrays.equals(array1, array2) 以避免混淆。

import java.util.Arrays;
public class ArrayDemo {
   public static void main(String[] args) {
   // initializing three object arrays
   Object[] array1 = new Object[] { 1, 123 };
   Object[] array2 = new Object[] { 1, 123, 22, 4 };
   Object[] array3 = new Object[] { 1, 123 };

   // comparing array1 and array2
   boolean retval=Arrays.equals(array1, array2);
   System.out.println("array1 and array2 equal: " + retval);
   System.out.println("array1 and array2 equal: " + array1.equals(array2));

   // comparing array1 and array3
   boolean retval2=Arrays.equals(array1, array3);
   System.out.println("array1 and array3 equal: " + retval2);
   System.out.println("array1 and array3 equal: " + array1.equals(array3));

   }
}

Here is the output:

    array1 and array2 equal: false
    array1 and array2 equal: false

    array1 and array3 equal: true
    array1 and array3 equal: false

Seeing this kind of problem I would personally go for Arrays.equals(array1, array2) as per your question to avoid confusion.

回心转意 2025-01-01 16:07:08

我认为 Objects.deepEquals(Obj1,Obj2) 是这里最好的统一解决方案,如果 Obj1 和 Obj2 是两个 int 数组,它会为您调用 Arrays.deepEquals0(a, b) 方法。如果您不比较字符串,它只会使用“.equals”(“==”)传统方法,因此在比较字符串时它也非常有用。

它将涵盖像黄油这样的正常用法,无需记住何时使用 ().equals()、Arrays.equals、(String a).equals((String b)) 或其他任何内容。

此 Objects.deepEquals 操作的时间复杂度将为 O(n)。

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

常见用法如下:
比较 int 数组,whooo:

int[] num1 = { 1, 2, 3, 4 };
int[] num2 = { 1, 2, 3, 4 };
System.out.println(Objects.deepEquals(num1, num2));

也可以比较 2D 数组,所以 gooooood:

int[][] nums1 = { { 1, 2 }, { 2, 3 }, { 3, 4 } };
int[][] nums2 = { { 1, 2 }, { 2, 3 }, { 3, 4 } };
System.out.println(Objects.deepEquals(nums1, nums2));

比较字符串,甚至更大:

String s1 = "sasfd!";
String s2 = "sasfd" + "!";
System.out.println(Objects.deepEquals(s1, s2));

I LOVE UNIVERSALLY APPLICABLE APPROACHES

I think the Objects.deepEquals(Obj1,Obj2) is the best uniform solution here, if Obj1 and Obj2 are two int arrays, it will call the Arrays.deepEquals0(a, b) method for you. If you are not comparing strings, it will just use the ".equals"("==") traditional method, so it is also very useful when comparing strings.

It will cover those normal usages like butter, no need to remember when to use ().equals(), Arrays.equals, (String a).equals((String b)) or whatsoever.

The time complexity of this Objects.deepEquals operation will be O(n).

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

Common usages are like:
Compare int array, whooo:

int[] num1 = { 1, 2, 3, 4 };
int[] num2 = { 1, 2, 3, 4 };
System.out.println(Objects.deepEquals(num1, num2));

Can also compare 2D arrays, so gooooood:

int[][] nums1 = { { 1, 2 }, { 2, 3 }, { 3, 4 } };
int[][] nums2 = { { 1, 2 }, { 2, 3 }, { 3, 4 } };
System.out.println(Objects.deepEquals(nums1, nums2));

Compare strings, even greater:

String s1 = "sasfd!";
String s2 = "sasfd" + "!";
System.out.println(Objects.deepEquals(s1, s2));

I LOVE UNIVERSALLY APPLICABLE APPROACHES

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文