Zauważ, że Arrays.equals()nie działa zgodnie z oczekiwaniami dla tablic wielowymiarowych, porównuje jedynie elementy z pierwszego wymiaru dla równości odniesienia. Apache commons ArrayUtils.isEqualswspółpracuje z tablicami wielowymiarowymi.
Adam Parkin,
4
Jestem oszołomiony. Czy istnieje powód, aby implementować array.equals do porównywania wskaźników zamiast porównywania długości i każdego obiektu?
Jezioro
2
@Lake is porównuje długość tablicy i zawartych w niej obiektów, ale nie robi to głębokiego porównania. Fakt równy działa zgodnie z oczekiwaniami, ponieważ tablice są zepsute, to nie powinno być problemem.
@JeewanthaSamaraweera, która jest definicją tej metody, jednak .equalsnie porównuje zawartości, dlatego właśnie potrzebujesz tej metody.
Peter Lawrey,
86
Jest to niesławny problem: .equals()ponieważ tablice są mocno zepsute, po prostu nigdy ich nie używaj.
To powiedziawszy, nie jest „zepsute”, jak w „ktoś zrobił to naprawdę źle” - po prostu robi to, co zdefiniowano, a nie to, czego zwykle się oczekuje. Tak więc dla purystów: jest całkowicie w porządku, a to oznacza również, że nigdy go nie używaj.
Teraz oczekiwanym zachowaniem equalsjest porównywanie danych. Domyślnym zachowaniem jest porównywanie tożsamości, ponieważ Objectnie ma żadnych danych (dla purystów: tak, ale nie o to chodzi); założeniem jest, że jeśli potrzebujesz equalsw podklasach, zaimplementujesz to. W tablicach nie ma dla ciebie żadnej implementacji, więc nie powinieneś jej używać.
Różnica polega na tym, że Arrays.equals(array1, array2)działa tak, jak można się spodziewać (tzn. Porównuje zawartość), array1.equals(array2)wraca do Object.equalsimplementacji, która z kolei porównuje tożsamość, a zatem lepiej zastępuje ją ==(dla purystów: tak, wiem o tym null).
Problem w tym, że nawet Arrays.equals(array1, array2)cię ugryzie, jeśli elementy tablicy nie zostaną equalspoprawnie zaimplementowane . To bardzo naiwne stwierdzenie, wiem, ale istnieje bardzo ważny, mniej oczywisty przypadek: rozważ tablicę 2D.
Tablica 2D w Javie to tablica tablic, a tablice equalssą zepsute (lub bezużyteczne, jeśli wolisz), więc Arrays.equals(array1, array2)nie będą działać tak, jak oczekujesz na tablicach 2D.
Czy tablica ma niestandardową implementację equals()? Myślałem, że nie zostało zastąpione przez Object.
Martijn Courteaux
@MichaelBorgwardt to biblioteka systemowa z metodą, która nie robi tego, co zostało powiedziane w javadoc. Brzmi dla mnie wystarczająco mocno. To powiedziawszy, przyznaję, że jest to bardzo dyskusyjna wypowiedź, ale wierzę, że „jest zepsute” lepiej zapamiętane, a zatem o wiele wygodniej jest myśleć o tym w ten sposób.
alf
@MartijnCourteaux to jest właśnie problem :)
alf.
3
W przypadku tablic tablic potrzebujesz Arrays.deepEquals--- to właśnie someArray.equalspowinno być zrobione przez cały czas. (Powiązane Objects.deepEquals
Kevin J. Chase
16
Zajrzyj do implementacji dwóch metod, aby je głęboko zrozumieć:
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
*/publicboolean equals(Object obj){return(this== obj);}
podczas:
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
*/publicstaticboolean equals(Object[] a,Object[] a2){if(a==a2)returntrue;if(a==null|| a2==null)returnfalse;int length = a.length;if(a2.length != length)returnfalse;for(int i=0; i<length; i++){Object o1 = a[i];Object o2 = a2[i];if(!(o1==null? o2==null: o1.equals(o2)))returnfalse;}returntrue;}
Westchnienie. W latach 70. byłem „programistą systemu” (sysadmin) dla systemu IBM 370, a mój pracodawca był członkiem grupy użytkowników IBM SHARE. Czasami zdarza się, że ktoś przedłożył raport APAR (raport o błędzie) dotyczący niektórych nieoczekiwanych zachowań niektórych poleceń CMS, a IBM zareaguje NOTABUG: polecenie wykonuje to, do czego zostało przeznaczone (i co mówi dokumentacja).
SHARE wymyślił coś przeciwnego: BAD - Broken As Designed. Myślę, że może to dotyczyć implementacji równości dla tablic.
Nie ma nic złego w implementacji Object.equals. Obiekt nie ma elementów danych, więc nie ma nic do porównania. Dwa „obiekty” są równe wtedy i tylko wtedy, gdy są w rzeczywistości tym samym obiektem (wewnętrznie ten sam adres i długość).
Ale ta logika nie dotyczy tablic. Tablice zawierają dane i oczekujesz porównania (poprzez równe), aby porównać dane. Najlepiej, jak robi to Arrays.deepEquals, ale przynajmniej tak, jak robi to Arrays.equals (płytkie porównanie elementów).
Problemem jest to, że tablica (jako obiekt wbudowany) nie zastępuje Object.equals. String (w nazwie klasy) robi override Object.equals i daje wynik można oczekiwać.
Inne podane odpowiedzi są poprawne: [...]. Równa się ([....]) po prostu porównuje wskaźniki, a nie zawartość. Może kiedyś ktoś to naprawi. A może nie: ile istniejących programów zepsułoby się, gdyby [...] równa się faktycznie porównać elementy? Podejrzewam, że niewiele, ale więcej niż zero.
equals()Tablic jest odziedziczony Object, więc nie patrzeć na treść arrrays, to tylko uważa każda tablica równe sobie.
Te Arrays.equals()metody nie porównać zawartość tablic. Istnieją przeciążenia dla wszystkich typów pierwotnych, a ten dla obiektów używa własnych equals()metod obiektów .
mówisz „zawartość tablic”, czy to oznacza także tablice wielowymiarowe?
AlanFoster
@AlanFoster: nie. Tablice wielowymiarowe są tablicami tablic, co oznacza, że będą wywoływane metody Arrays.equals (Object [], Object []), które wywołują metody equals () pod-tablic
Michael Borgwardt
0
import java.util.Arrays;publicclassArrayDemo{publicstaticvoid main(String[] args){// initializing three object arraysObject[] array1 =newObject[]{1,123};Object[] array2 =newObject[]{1,123,22,4};Object[] array3 =newObject[]{1,123};// comparing array1 and array2boolean 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 array3boolean retval2=Arrays.equals(array1, array3);System.out.println("array1 and array3 equal: "+ retval2);System.out.println("array1 and array3 equal: "+ array1.equals(array3));}}
Oto wynik:
array1 and array2 equal:false
array1 and array2 equal:false
array1 and array3 equal:true
array1 and array3 equal:false
Widząc tego rodzaju problem, osobiście wybrałbym Arrays.equals(array1, array2)według twojego pytania, aby uniknąć zamieszania.
Wydaje się, że jest poprawny, ale w przypadku tablic ważna jest również kolejność elementów. Na przykład, jeśli istnieje inna tablica Object [] array4 = new Object [] {123, 1}; z Arrays.equals (array3, array4), zwróci false.
Odpowiedzi:
array1.equals(array2)
jest taki sam jakarray1 == array2
, tj. czy jest to ta sama tablica. Jak zauważa @alf, większość ludzi tego nie oczekuje.Arrays.equals(array1, array2)
porównuje zawartość tablic.Podobnie
array.toString()
może nie być bardzo przydatne i musisz go użyćArrays.toString(array)
.źródło
Arrays.equals()
nie działa zgodnie z oczekiwaniami dla tablic wielowymiarowych, porównuje jedynie elementy z pierwszego wymiaru dla równości odniesienia. Apache commonsArrayUtils.isEquals
współpracuje z tablicami wielowymiarowymi.Arrays.deepEquals(Object[], Object[])
..equals
nie porównuje zawartości, dlatego właśnie potrzebujesz tej metody.Jest to niesławny problem:
.equals()
ponieważ tablice są mocno zepsute, po prostu nigdy ich nie używaj.To powiedziawszy, nie jest „zepsute”, jak w „ktoś zrobił to naprawdę źle” - po prostu robi to, co zdefiniowano, a nie to, czego zwykle się oczekuje. Tak więc dla purystów: jest całkowicie w porządku, a to oznacza również, że nigdy go nie używaj.
Teraz oczekiwanym zachowaniem
equals
jest porównywanie danych. Domyślnym zachowaniem jest porównywanie tożsamości, ponieważObject
nie ma żadnych danych (dla purystów: tak, ale nie o to chodzi); założeniem jest, że jeśli potrzebujeszequals
w podklasach, zaimplementujesz to. W tablicach nie ma dla ciebie żadnej implementacji, więc nie powinieneś jej używać.Różnica polega na tym, że
Arrays.equals(array1, array2)
działa tak, jak można się spodziewać (tzn. Porównuje zawartość),array1.equals(array2)
wraca doObject.equals
implementacji, która z kolei porównuje tożsamość, a zatem lepiej zastępuje ją==
(dla purystów: tak, wiem o tymnull
).Problem w tym, że nawet
Arrays.equals(array1, array2)
cię ugryzie, jeśli elementy tablicy nie zostanąequals
poprawnie zaimplementowane . To bardzo naiwne stwierdzenie, wiem, ale istnieje bardzo ważny, mniej oczywisty przypadek: rozważ tablicę 2D.Tablica 2D w Javie to tablica tablic, a tablice
equals
są zepsute (lub bezużyteczne, jeśli wolisz), więcArrays.equals(array1, array2)
nie będą działać tak, jak oczekujesz na tablicach 2D.Mam nadzieję, że to pomaga.
źródło
equals()
? Myślałem, że nie zostało zastąpione przez Object.Arrays.deepEquals
--- to właśniesomeArray.equals
powinno być zrobione przez cały czas. (PowiązaneObjects.deepEquals
Zajrzyj do implementacji dwóch metod, aby je głęboko zrozumieć:
podczas:
źródło
Westchnienie. W latach 70. byłem „programistą systemu” (sysadmin) dla systemu IBM 370, a mój pracodawca był członkiem grupy użytkowników IBM SHARE. Czasami zdarza się, że ktoś przedłożył raport APAR (raport o błędzie) dotyczący niektórych nieoczekiwanych zachowań niektórych poleceń CMS, a IBM zareaguje NOTABUG: polecenie wykonuje to, do czego zostało przeznaczone (i co mówi dokumentacja).
SHARE wymyślił coś przeciwnego: BAD - Broken As Designed. Myślę, że może to dotyczyć implementacji równości dla tablic.
Nie ma nic złego w implementacji Object.equals. Obiekt nie ma elementów danych, więc nie ma nic do porównania. Dwa „obiekty” są równe wtedy i tylko wtedy, gdy są w rzeczywistości tym samym obiektem (wewnętrznie ten sam adres i długość).
Ale ta logika nie dotyczy tablic. Tablice zawierają dane i oczekujesz porównania (poprzez równe), aby porównać dane. Najlepiej, jak robi to Arrays.deepEquals, ale przynajmniej tak, jak robi to Arrays.equals (płytkie porównanie elementów).
Problemem jest to, że tablica (jako obiekt wbudowany) nie zastępuje Object.equals. String (w nazwie klasy) robi override Object.equals i daje wynik można oczekiwać.
Inne podane odpowiedzi są poprawne: [...]. Równa się ([....]) po prostu porównuje wskaźniki, a nie zawartość. Może kiedyś ktoś to naprawi. A może nie: ile istniejących programów zepsułoby się, gdyby [...] równa się faktycznie porównać elementy? Podejrzewam, że niewiele, ale więcej niż zero.
źródło
Tablice dziedziczą
equals()
odObject
a więc porównać tylko zwraca true jeśli porównać tablicę przeciwko sobie.Z drugiej strony
Arrays.equals
porównuje elementy tablic.Ten fragment wyjaśnia różnicę:
Zobacz także
Arrays.equals()
. Inna metoda statyczna może być także interesujące:Arrays.deepEquals()
.źródło
Arrays.equals(array1, array2)
:sprawdź, czy obie tablice zawierają tę samą liczbę elementów i czy wszystkie odpowiednie pary elementów w dwóch tablicach są równe.
array1.equals(array2)
:porównaj obiekt z innym obiektem i zwróć wartość true tylko wtedy, gdy odwołanie do dwóch obiektów jest równe jak w
Object.equals()
źródło
equals()
Tablic jest odziedziczonyObject
, więc nie patrzeć na treść arrrays, to tylko uważa każda tablica równe sobie.Te
Arrays.equals()
metody nie porównać zawartość tablic. Istnieją przeciążenia dla wszystkich typów pierwotnych, a ten dla obiektów używa własnychequals()
metod obiektów .źródło
Oto wynik:
Widząc tego rodzaju problem, osobiście wybrałbym
Arrays.equals(array1, array2)
według twojego pytania, aby uniknąć zamieszania.źródło