Порівнюючи масиви в Java, чи є різниці між наступними 2 твердженнями?
Object[] array1, array2;
array1.equals(array2);
Arrays.equals(array1, array2);
А якщо так, то які вони?
Порівнюючи масиви в Java, чи є різниці між наступними 2 твердженнями?
Object[] array1, array2;
array1.equals(array2);
Arrays.equals(array1, array2);
А якщо так, то які вони?
Відповіді:
array1.equals(array2)
це те саме array1 == array2
, що є, тобто це той самий масив. Як зазначає @alf, більшість людей не очікують цього.
Arrays.equals(array1, array2)
порівнює вміст масивів.
Так само array.toString()
може бути не дуже корисним і вам потрібно скористатися Arrays.toString(array)
.
Arrays.equals()
не працює, як очікувалося, для багатовимірних масивів, він лише порівнює елементи 1-го виміру для еталонної рівності. Apache commons ArrayUtils.isEquals
працює з багатовимірними масивами.
Arrays.deepEquals(Object[], Object[])
.
.equals
він не порівнює вміст, саме тому вам потрібен цей метод.
Це сумнозвісна проблема: .equals()
адже масиви сильно розбиті, просто не використовуйте їх ніколи.
Однак це не "зламано", як "хтось зробив це по-справжньому неправильно" - це просто те, що визначено, а не те, що зазвичай очікується. Тож для пуристів: це прекрасно, а це також означає, що не використовуйте його ніколи.
Тепер очікувана поведінка для equals
порівняння даних. Типовою поведінкою є порівняння ідентичності, оскільки Object
не має жодних даних (для пуристів: так, але це не в цьому); припущення, якщо вам потрібно equals
в підкласах, ви будете його реалізовувати. У масивах для вас немає жодної реалізації, тому ви не повинні її використовувати.
Таким чином, різниця в тому, Arrays.equals(array1, array2)
працює , як можна було б очікувати (тобто порівнює зміст), array1.equals(array2)
повертається до Object.equals
реалізації, що , в свою чергу , порівнює ідентичність, і , таким чином , краще замінити на ==
(для пуристів: так , я знаю про null
).
Проблема навіть у Arrays.equals(array1, array2)
тому, що елементи масиву не реалізуються equals
належним чином. Я знаю, це дуже наївне твердження, але є дуже важливий менш очевидний випадок: розгляньте 2D масив.
2D масив на Java - це масив масивів, а масиви ' equals
порушені (або марні, якщо ви віддаєте перевагу), тому Arrays.equals(array1, array2)
не працюватимуть так, як ви очікували на 2D масивах.
Сподіваюся, що це допомагає.
equals()
? Я думав, що це не було відмінено від Object.
Arrays.deepEquals
--- це те, що someArray.equals
повинно було робитися весь час. (Споріднено:. Objects.deepEquals
)
Загляньте всередину реалізації двох методів, щоб глибше їх зрозуміти:
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);
}
поки:
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;
}
Зітхнути. Ще в 70-х я був «системним програмістом» (sysadmin) для системи IBM 370, і мій роботодавець був членом групи користувачів IBM SHARE. Іноді трапляється, що хтось подав APAR (звіт про помилку) про якусь несподівану поведінку якоїсь команди CMS, і IBM відповість NOTABUG: команда робить те, що було призначено для виконання (і що говорить документація).
ПОДІЛИТИ придумали лічильник цього: BAD - Broken As Design. Я думаю, це може стосуватися цієї реалізації рівних для масивів.
З реалізацією Object.equals немає нічого поганого. Об'єкт не має членів даних, тому порівняти нема з чим. Два "Об'єкта" є рівними, якщо і тільки тоді, якщо вони насправді є одним і тим же Об'єктом (внутрішньо однакова адреса і довжина).
Але ця логіка не застосовується до масивів. Масиви мають дані, і ви очікуєте порівняння (через рівні) для порівняння даних. В ідеалі - так, як це робить Arrays.deepEquals, але принаймні так, як Arrays.equals (дрібне порівняння елементів).
Отже, проблема полягає в тому, що масив (як вбудований об'єкт) не перекриває Object.equals. String (як іменований клас) робить перевизначення Object.equals і дати результат , який ви очікуєте.
Інші наведені відповіді є правильними: [...]. Equals ([....]) просто порівнює вказівники, а не вміст. Можливо, колись хтось це виправить. А може й ні: скільки існуючих програм зламається, якщо [...]. Рівний насправді порівнював елементи? Підозрюю, не багато, але більше нуля.
Масиви успадковані equals()
від Object
і , отже , порівнювати тільки повертає істину , якщо порівнювати масив проти себе.
З іншого боку, 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()
.
The Arrays.equals(array1, array2)
:
перевірте, чи містять обидва масиви однакову кількість елементів, і всі відповідні пари елементів у двох масивах рівні.
The array1.equals(array2)
:
порівняйте об'єкт з іншим об'єктом та поверніть істинне, лише якщо посилання на два об'єкти рівні, як у Object.equals()
Архів equals()
масивів успадковується Object
, тому він не розглядає вміст масивів, він лише вважає кожен масив рівним собі.
Ці Arrays.equals()
методи дійсно порівняти вміст масивів. Існує перевантаження для всіх примітивних типів, а одна для об'єктів використовує власні equals()
методи об'єктів .
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)
за вашим запитанням, щоб уникнути плутанини.