Arrays.deepEquals

1. Общ преглед

В този урок ще се потопим в детайлите на метода deepEquals от класа Arrays . Ще видим кога трябва да използваме този метод и ще разгледаме няколко прости примера.

За да научите повече за различните методи в класа java.util.Arrays , разгледайте нашето кратко ръководство.

2. Цел

Трябва да използваме метода deepEquals , когато искаме да проверим равенството между два вложени или многомерни масива . Също така, когато искаме да сравним два масива, съставени от дефинирани от потребителя обекти, както ще видим по-късно, трябва да заменим метода equals .

Сега, нека разберем повече подробности за метода deepEquals .

2.1. Синтаксис

Ще започнем, като разгледаме подписа на метода :

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

От сигнатурата на метода забелязваме, че не можем да използваме deepEquals за сравняване на два едномерни масива от примитивни типове данни . За целта трябва или да прикачим примитивния масив към съответната му обвивка, или да използваме метода Arrays.equals , който има претоварени методи за примитивни масиви.

2.2. Изпълнение

Анализирайки вътрешната реализация на метода, можем да видим, че методът не само проверява елементите от най-високо ниво на масивите, но и проверява рекурсивно всеки негов поделемент .

Следователно трябва да избягваме използването на метода deepEquals с масиви, които имат самопрепратка, защото това ще доведе до java.lang.StackOverflowError .

След това нека разберем какъв изход можем да получим от този метод.

3. Изход

Методът Arrays.deepEquals връща:

  • вярно, ако и двата параметъра са един и същ обект (имат една и съща препратка)
  • вярно, ако и двата параметъра са нула
  • false, ако само един от двата параметъра е нула
  • false, ако масивите имат различна дължина
  • истина, ако и двата масива са празни
  • вярно, ако масивите съдържат еднакъв брой елементи и всяка двойка поделементи са дълбоко равни
  • false в други случаи

В следващия раздел ще разгледаме някои примери за код.

4. Примери

Сега е време да започнете да разглеждате метода deepEquals в действие. Освен това ще сравним метода deepEquals с метода equals от същия клас Arrays .

4.1. Едномерни масиви

Първо, нека започнем с прост пример и да сравним два едномерни масива от тип 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));

Виждаме, че методите equals и deepEquals връщат true . Нека да разберем какво се случва, ако един елемент от нашите масиви е нулев :

 Object[] anArray = new Object[] { "string1", null, "string3" }; Object[] anotherArray = new Object[] { "string1", null, "string3" }; assertTrue(Arrays.equals(anArray, anotherArray)); assertTrue(Arrays.deepEquals(anArray, anotherArray));

Виждаме, че и двете твърдения преминават. Следователно можем да заключим, че когато се използва методът deepEquals , се приемат нулеви стойности на всяка дълбочина на входните масиви .

Но нека опитаме още нещо и нека проверим поведението с вложени масиви:

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

Тук ще открием, че deepEquals връща true, а equals връща false . Това е така, защото deepEquals се извиква рекурсивно, когато среща масив , докато equals просто сравнява препратките на под-масивите.

4.2. Многомерни масиви от примитивни типове

След това нека проверим поведението с помощта на многомерни масиви. В следващия пример двата метода имат различни изходи, подчертавайки факта, че трябва да използваме 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. Многомерни масиви от дефинирани от потребителя обекти

И накрая, нека проверим поведението на deepEquals и equals методи при тестване на равенството на два многомерни масива за дефиниран от потребителя обект:

Нека започнем със създаването на прост клас 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; } }

Необходимо е да се замени методът equals за нашия клас Person . В противен случай методът по подразбиране е равно ще сравнява само референциите на обектите.

Също така, нека вземем предвид, че макар да не е от значение за нашия пример, ние винаги трябва да заместваме hashCode, когато заместваме метода equals , за да не нарушаваме техните договори.

След това можем да сравним два многомерни масива от класа 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));

В резултат на рекурсивно сравняване на поделементите, двата метода отново имат различни резултати.

И накрая, заслужава да се спомене, че методът Objects.deepEquals изпълнява вътрешно метода Arrays.deepEquals , когато е извикан с два масива Object :

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

5. Заключение

В този бърз урок научихме, че трябва да използваме метода Arrays.deepEquals , когато искаме да сравним равенството между два вложени или многомерни масива от обекти или примитивни типове .

Както винаги, пълният изходен код на статията е достъпен в GitHub.