Java 中的 equals 与 Arrays.equals
在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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
array1.equals(array2)
与array1 == array2
相同,即是否是同一个数组。 正如 @alf 指出的,这并不是大多数人所期望的。Arrays.equals(array1, array2)
比较数组的内容。同样,
array.toString()
可能不是很有用,您需要使用Arrays.toString(array)
。array1.equals(array2)
is the same asarray1 == 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 useArrays.toString(array)
.这是一个臭名昭著的问题:数组的
.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, asObject
does not have any data (for purists: yes it has, but it's not the point); assumption is, if you needequals
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 toObject.equals
implementation, which in turn compares identity, and thus better replaced by==
(for purists: yes I know aboutnull
).Problem is, even
Arrays.equals(array1, array2)
will bite you hard if elements of array do not implementequals
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), soArrays.equals(array1, array2)
will not work as you expect on 2D arrays.查看这两个方法的实现内部以深入理解它们:
while:
Look inside the implementation of the two methods to understand them deeply:
while:
叹。早在 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.
数组从
Object
继承equals()
,因此只有在将数组与自身进行比较时,compare 才会返回 true。另一方面,Arrays.equals 比较数组的元素。
此代码片段阐明了差异:
另请参阅
Arrays.equals()
。另一个静态方法可能也令人感兴趣:Arrays.deepEquals()
。Arrays inherit
equals()
fromObject
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:
See also
Arrays.equals()
. Another static method there may also be of interest:Arrays.deepEquals()
.数组的
equals()
是从Object
继承的,所以它不看数组的内容,它只认为每个数组都等于它自己。Arrays.equals()
方法do比较数组的内容。所有基本类型都有重载,而对象的重载则使用对象自己的equals()
方法。The
equals()
of arrays is inherited fromObject
, 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' ownequals()
methods.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()
这是输出:
看到这种问题,我个人会根据您的问题使用 Arrays.equals(array1, array2) 以避免混淆。
Here is the output:
Seeing this kind of problem I would personally go for
Arrays.equals(array1, array2)
as per your question to avoid confusion.我认为 Objects.deepEquals(Obj1,Obj2) 是这里最好的统一解决方案,如果 Obj1 和 Obj2 是两个 int 数组,它会为您调用 Arrays.deepEquals0(a, b) 方法。如果您不比较字符串,它只会使用“.equals”(“==”)传统方法,因此在比较字符串时它也非常有用。
它将涵盖像黄油这样的正常用法,无需记住何时使用 ().equals()、Arrays.equals、(String a).equals((String b)) 或其他任何内容。
此 Objects.deepEquals 操作的时间复杂度将为 O(n)。
常见用法如下:
比较 int 数组,whooo:
也可以比较 2D 数组,所以 gooooood:
比较字符串,甚至更大:
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).
Common usages are like:
Compare int array, whooo:
Can also compare 2D arrays, so gooooood:
Compare strings, even greater:
I LOVE UNIVERSALLY APPLICABLE APPROACHES