Java Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

1. Overview

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.

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

2. Purpose

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.

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

2.1. Syntax

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.

2.2. Implementation

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.

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

3. Output

The Arrays.deepEquals method returns:

  • 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

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.

4.1. Unidimensional Arrays

Firstly, let's start with a simple example and compare two unidimensional arrays of type 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:

    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.

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.

4.2. Multidimensional Arrays of Primitive Types

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:

    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

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

Let's start by creating a simple Person class:

    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.

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.

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

    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:

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

5. Conclusion

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.

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

Java bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE
Comments are closed on this article!