Arrays.deepEquals – Arrays.deepEquals

最后修改: 2020年 2月 20日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll dive into the details of the deepEquals method from the Arrays class. We’ll see when we should use this method, and we’ll go through some simple examples.

在本教程中,我们将深入了解Arrays类中的deepEquals方法的细节。我们将看到什么时候应该使用这个方法,并将通过一些简单的例子。

To learn more about the different methods in the java.util.Arrays class, check out our quick guide.

要了解关于java.util.Arrays类中不同方法的更多信息,请查看我们的快速指南

2. Purpose

2.宗旨

We should use the deepEquals method when we want to check the equality between two nested or multidimensional arrays. Also, when we want to compare two arrays composed of user-defined objects, as we’ll see later, we must override the equals method.

当我们想检查两个嵌套的或多维的数组之间是否相等时,我们应该使用deepEquals方法。另外,当我们想比较两个由用户定义的对象组成的数组时,正如我们将在后面看到的,我们必须覆盖equals方法。

Now, let’s find out more details about the deepEquals method.

现在,让我们了解一下deepEquals方法的更多细节。

2.1. Syntax

2.1 语法

We’ll start by having a look at the method signature:

我们先来看看方法签名

public static boolean deepEquals(Object[] a1, Object[] a2)

From the method signature, we notice that we cannot use deepEquals to compare two unidimensional arrays of primitive data types. For this, we must either box the primitive array to its corresponding wrapper or use the Arrays.equals method, which has overloaded methods for primitive arrays.

从方法签名中,我们注意到我们不能使用deepEquals来比较两个原始数据类型的一维数组。为此,我们必须将原始数组装箱到其相应的包装器中,或者使用Arrays.equals方法,该方法对原始数组有重载方法。

2.2. Implementation

2.2.实施

By analyzing the method’s internal implementation, we can see that the method not only checks the top-level elements of the arrays but also checks recursively every subelement of it.

通过分析该方法的内部实现,我们可以看到该方法不仅检查数组的顶层元素,而且还递归地检查它的每一个子元素

Therefore, we should avoid using the deepEquals method with arrays that have a self-reference because this will result in a java.lang.StackOverflowError.

因此,我们应该避免对有自我引用的数组使用deepEquals方法,因为这将导致java.lang.StackOverflowError

Next, let’s find out what output we can get from this method.

接下来,让我们看看从这个方法中可以得到什么输出。

3. Output

3.输出

The Arrays.deepEquals method returns:

Arrays.deepEquals方法返回。

  • true if both parameters are the same object (have the same reference)
  • true if both parameters are null
  • false if only one of the two parameters is null
  • false if the arrays have different lengths
  • true if both arrays are empty
  • true if the arrays contain the same number of elements and every pair of subelements are deeply equal
  • false in other cases

In the next section, we’ll have a look at some code examples.

在下一节中,我们将看一下一些代码实例。

4. Examples

4.实例

Now it’s time to start looking at deepEquals method in action. Moreover, we’ll compare the deepEquals method with the equals method from the same Arrays class.

现在是时候开始看一下deepEquals方法的操作了。此外,我们将把deepEquals方法与同一Arrays类中的equals方法进行比较。

4.1. Unidimensional Arrays

4.1. 一维数组

Firstly, let’s start with a simple example and compare two unidimensional arrays of type Object:

首先,让我们从一个简单的例子开始,比较两个Object类型的单维数组。

    Object[] anArray = new Object[] { "string1", "string2", "string3" };
    Object[] anotherArray = new Object[] { "string1", "string2", "string3" };

    assertTrue(Arrays.equals(anArray, anotherArray));
    assertTrue(Arrays.deepEquals(anArray, anotherArray));

We see that both equals and deepEquals methods return true. Let’s find out what happens if one element of our arrays is null:

我们看到,equalsdeepEquals方法都返回true。让我们来看看如果数组中的一个元素是null会发生什么。

    Object[] anArray = new Object[] { "string1", null, "string3" };
    Object[] anotherArray = new Object[] { "string1", null, "string3" };

    assertTrue(Arrays.equals(anArray, anotherArray));
    assertTrue(Arrays.deepEquals(anArray, anotherArray));

We see that both assertions are passing. Hence, we can conclude that when using the deepEquals method, null values are accepted at any depth of the input arrays.

我们看到,两个断言都通过了。因此,我们可以得出结论,当使用deepEquals方法时,null值在输入数组的任何深度都可以接受

But let’s try one more thing and let’s check the behavior with nested arrays:

但让我们再试一下,让我们检查一下嵌套数组的行为。

    Object[] anArray = new Object[] { "string1", null, new String[] {"nestedString1", "nestedString2" }};
    Object[] anotherArray = new Object[] { "string1", null, new String[] {"nestedString1", "nestedString2" } };

    assertFalse(Arrays.equals(anArray, anotherArray));
    assertTrue(Arrays.deepEquals(anArray, anotherArray));

Here we find out that the deepEquals returns true while equals returns false. This is because deepEquals calls itself recursively when encountering an array, while equals just compares the references of the sub-arrays.

这里我们发现,deepEquals返回true,而equals返回false。这是因为deepEquals在遇到数组时递归调用自己,而equals只是对子数组的引用进行比较。

4.2. Multidimensional Arrays of Primitive Types

4.2.原始类型的多维数组

Next, let’s check the behavior using multidimensional arrays. In the next example, the two methods have different outputs, emphasizing the fact that we should use deepEquals instead of the equals method when we are comparing multidimensional arrays:

接下来,让我们检查一下使用多维数组的行为。在下一个例子中,两个方法有不同的输出,强调了这样一个事实:当我们比较多维数组时,我们应该使用deepEquals而不是equals方法。

    int[][] anArray = { { 1, 2, 3 }, { 4, 5, 6, 9 }, { 7 } };
    int[][] anotherArray = { { 1, 2, 3 }, { 4, 5, 6, 9 }, { 7 } };

    assertFalse(Arrays.equals(anArray, anotherArray));
    assertTrue(Arrays.deepEquals(anArray, anotherArray));

4.3. Multidimensional Arrays of User-Defined Objects

4.3.用户定义的对象的多维数组

Finally, let’s check the behavior of deepEquals and equals methods when testing the equality of two multidimensional arrays for a user-defined object:

最后,让我们检查一下deepEqualsequals方法在测试一个用户定义的对象的两个多维数组相等时的行为。

Let’s start by creating a simple Person class:

让我们从创建一个简单的Person类开始。

    class Person {
        private int id;
        private String name;
        private int age;

        // constructor & getters & setters

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (!(obj instanceof Person))
                return false;
            Person person = (Person) obj;
            return id == person.id && name.equals(person.name) && age == person.age;
        }
    }

It is necessary to override the equals method for our Person class. Otherwise, the default equals method will compare only the references of the objects.

对于我们的Person类,有必要覆盖equals方法。否则,默认的equals方法将只比较对象的引用。

Also, let’s take into consideration that, even though it’s not relevant for our example, we should always override hashCode when we override the equals method so that we don’t violate their contracts.

另外,让我们考虑一下,尽管这与我们的例子无关,但当我们覆盖equals方法时,我们应该总是覆盖hashCode,这样我们就不会违反他们的contracts

Next, we can compare two multidimensional arrays of the Person class:

接下来,我们可以比较Person类的两个多维数组。

    Person personArray1[][] = { { new Person(1, "John", 22), new Person(2, "Mike", 23) },
      { new Person(3, "Steve", 27), new Person(4, "Gary", 28) } };
    Person personArray2[][] = { { new Person(1, "John", 22), new Person(2, "Mike", 23) }, 
      { new Person(3, "Steve", 27), new Person(4, "Gary", 28) } };
        
    assertFalse(Arrays.equals(personArray1, personArray2));
    assertTrue(Arrays.deepEquals(personArray1, personArray2));

As a result of recursively comparing the subelements, the two methods again have different results.

作为递归比较子元素的结果,两种方法又有不同的结果。

Finally, it is worth mentioning that the Objects.deepEquals method executes the Arrays.deepEquals method internally when it is called with two Object arrays:

最后,值得一提的是,Objects.deepEquals方法在内部执行Arrays.deepEquals方法,当它被调用到两个Object数组时,

    assertTrue(Objects.deepEquals(personArray1, personArray2));

5. Conclusion

5.总结

In this quick tutorial, we learned that we should use the Arrays.deepEquals method when we want to compare the equality between two nested or multi-dimensional arrays of objects or primitive types.

在这个快速教程中,我们了解到,当我们想比较两个对象或原始类型的嵌套或多维数组之间的等价物时,我们应该使用Arrays.deepEquals方法。

As always, the full source code of the article is available over on GitHub.

一如既往,文章的完整源代码可在GitHub上获得over。