równe vs Tablice.równe w Javie

Porównując tablice w Javie, czy istnieją jakieś różnice między następującymi 2 instrukcjami?

array1.equals(array2);
Arrays.equals(array1, array2);
A jeśli tak, to czym one są?
Author: PandaConda, 2012-01-08

8 answers

array1.equals(array2) jest tym samym co array1 == array2, tzn. jest tą samą tablicą. Jak podkreśla @alf, to nie jest to, czego oczekuje większość ludzi.

Arrays.equals(array1, array2) porównuje zawartość tablic.


Podobnie array.toString() może nie być zbyt przydatne i musisz użyć Arrays.toString(array).

 264
Author: Peter Lawrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-01 16:19:20

To niesławny problem: .equals() dla tablic jest źle uszkodzony, po prostu nie używaj go, nigdy.

To powiedziane, to nie jest " złamane "jak w" Ktoś zrobił to w naprawdę zły sposób " - to po prostu robi to, co jest zdefiniowane, a nie to, co zwykle oczekuje. Więc dla purystów: jest to całkowicie w porządku, a to również oznacza, nigdy nie używaj tego.

Teraz oczekiwanym zachowaniem dla {[1] } jest porównanie danych. Domyślnym zachowaniem jest porównanie tożsamości, ponieważ Object nie posiada żadnych danych (dla purystów: tak, ale nie o to chodzi); założenie jest takie, że jeśli potrzebujesz equals w podklasach, zaimplementujesz to. W tablicach nie ma dla Ciebie implementacji, więc nie powinieneś jej używać.

Różnica polega więc na tym, że Arrays.equals(array1, array2) działa tak, jak można się spodziewać (tzn. porównuje treść), array1.equals(array2) wraca do Object.equals implementacji, która z kolei porównuje tożsamość, a zatem lepiej zastępuje ją == (Dla purystów: tak, Wiem o null).

Problem w tym, że nawet Arrays.equals(array1, array2) ugryzie cię trudno, jeśli elementy tablicy nie implementują equals poprawnie. Wiem, że to bardzo naiwne stwierdzenie, ale jest bardzo ważny, mniej niż oczywisty przypadek: rozważ tablicę 2D.

Tablica 2D w języku Java jest tablicą tablic, a tablica equals jest zepsuta (lub bezużyteczna, jeśli wolisz), więc Arrays.equals(array1, array2) nie będzie działać tak, jak oczekujesz na tablicach 2D.

Mam nadzieję, że to pomoże.
 75
Author: alf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-19 11:51:02

Zajrzyj do implementacji tych dwóch metod, aby zrozumieć je głęboko:

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

While:

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;
}
 15
Author: Eng.Fouad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-08 12:13:29

Westchnienie W latach 70. byłem "programistą systemu" (sysadmin) dla systemu IBM 370, a mój pracodawca był członkiem IBM users group SHARE. Czasami zdarza się, że ktoś zgłosił APAR (bug report) na nieoczekiwane zachowanie jakiegoś polecenia CMS, a IBM zareagował NOTABUG: polecenie robi to, do czego zostało zaprojektowane (i co mówi dokumentacja).

SHARE wymyślił licznik do tego: BAD -- Broken As Designed. Myślę, że to może dotyczyć tego implementacja równań dla tablic.

Nie ma nic złego w implementacji obiektu.równi. Obiekt nie ma elementów składowych danych, więc nie ma co porównywać. Dwa "obiekty" są równe wtedy i tylko wtedy, gdy są w rzeczywistości tym samym obiektem (wewnętrznie, tym samym adresem i długością).

Ale ta logika nie dotyczy tablic. Macierze mają Dane i oczekujesz porównania (poprzez równe), aby porównać dane. Idealnie, sposób Tablice.deepEquals tak, ale przynajmniej tak jak tablice.equals does (płytkie porównanie elementów).

Problem polega na tym, że tablica (jako obiekt Wbudowany) nie nadpisuje obiektu.równi. String (jako nazwana Klasa) nadpisuje obiekt .równa się i dać wynik, którego oczekujesz.

Inne podane odpowiedzi są poprawne: [...].równa ([....]) po prostu porównuje wskaźniki, a nie zawartość. Może kiedyś ktoś to poprawi. A może nie: ile istniejących programów by się zepsuło, gdyby [...].równi rzeczywiście porównali elementy? Nie podejrzewam, że wiele, ale więcej niż zero.

 8
Author: A. P. Damien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-29 16:54:47

Tablice dziedziczą equals() z Object i dlatego compare zwraca true tylko wtedy, gdy porównuje tablicę z samą sobą.

Z drugiej strony, Arrays.equals porównuje elementy tablic.

Ten fragment wyjaśnia różnicę:

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

Zobacz Arrays.equals(). Inna statyczna metoda może być również interesująca: Arrays.deepEquals().

 5
Author: Adam Zalcman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-08 12:01:25

Arrays.equals(array1, array2):

Sprawdź, czy obie tablice zawierają tę samą liczbę elementów, a wszystkie odpowiadające im pary elementów w obu tablicach są równe.

array1.equals(array2):

Porównaj obiekt z innym obiektem i zwróć true tylko wtedy, gdy odniesienie do dwóch obiektów jest równe jak w Object.equals()

 1
Author: aleroot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-08 12:01:20

equals() tablic jest dziedziczona z Object, więc nie patrzy na zawartość arrrays, tylko uważa każdą tablicę równą sobie.

Metody Arrays.equals() porównują zawartość tablic. Istnieje przeciążenie dla wszystkich typów prymitywnych, a ten dla obiektów używa własnych metod equals() obiektów.

 0
Author: Michael Borgwardt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-08 11:59:03
import java.util.Arrays;
public class ArrayDemo {
   public static void main(String[] args) {
   // initiliazing three object arrays
   Object[] arr1 = new Object[] { 1, 123 };
   Object[] arr2 = new Object[] { 1, 123, 22, 4 };
   Object[] arr3 = new Object[] { 1, 123 };

   // comparing arr1 and arr2
   boolean retval=Arrays.equals(arr1, arr2);
   System.out.println("arr1 and arr2 equal: " + retval);
   System.out.println("arr1 and arr2 equal: " + arr1.equals(arr2));

   // comparing arr1 and arr3
   boolean retval2=Arrays.equals(arr1, arr3);
   System.out.println("arr1 and arr3 equal: " + retval2);
   System.out.println("arr1 and arr2 equal: " + arr1.equals(arr3));

   }
}

Oto wyjście:

    arr1 and arr2 equal: false
    arr1 and arr2 equal: false

    arr1 and arr3 equal: true
    arr1 and arr3 equal: false
Widząc ten rodzaj problemu osobiście wybrałbym Arrays.equals(array1, array2) zgodnie z twoim pytaniem, aby uniknąć zamieszania.
 0
Author: Tayyab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-15 00:54:45