Gibt es beim Vergleich von Arrays in Java Unterschiede zwischen den folgenden beiden Anweisungen?
Object[] array1, array2;
array1.equals(array2);
Arrays.equals(array1, array2);
Und wenn ja, was sind sie?
Gibt es beim Vergleich von Arrays in Java Unterschiede zwischen den folgenden beiden Anweisungen?
Object[] array1, array2;
array1.equals(array2);
Arrays.equals(array1, array2);
Und wenn ja, was sind sie?
Antworten:
array1.equals(array2)
ist das gleiche wie array1 == array2
, dh es ist das gleiche Array. Wie @alf betont, ist es nicht das, was die meisten Leute erwarten.
Arrays.equals(array1, array2)
vergleicht den Inhalt der Arrays.
Ebenso array.toString()
kann nicht sehr nützlich sein und Sie müssen verwenden Arrays.toString(array)
.
Arrays.equals()
dies für mehrdimensionale Arrays nicht wie erwartet funktioniert, sondern nur Elemente der 1. Dimension auf Referenzgleichheit vergleicht. Apache Commons ArrayUtils.isEquals
arbeitet mit mehrdimensionalen Arrays.
Arrays.deepEquals(Object[], Object[])
.
.equals
es vergleicht keine Inhalte, weshalb Sie diese Methode benötigen.
Es ist ein berüchtigtes Problem: .equals()
Da Arrays stark beschädigt sind, verwenden Sie sie niemals.
Das heißt, es ist nicht "kaputt" wie in "jemand hat es wirklich falsch gemacht" - es macht nur das, was definiert ist und nicht das, was normalerweise erwartet wird. Also für Puristen: Es ist vollkommen in Ordnung, und das bedeutet auch, es niemals zu benutzen.
Das erwartete Verhalten für equals
besteht nun darin, Daten zu vergleichen. Das Standardverhalten besteht darin, die Identität zu vergleichen, da Object
keine Daten vorhanden sind (für Puristen: Ja, aber es geht nicht darum). Annahme ist, wenn Sie equals
in Unterklassen benötigen , werden Sie es implementieren. In Arrays gibt es keine Implementierung für Sie, daher sollten Sie sie nicht verwenden.
Der Unterschied ist also, Arrays.equals(array1, array2)
funktioniert wie erwartet (dh vergleicht Inhalt), array1.equals(array2)
fällt zurück Object.equals
Implementierung, was wiederum Identität vergleicht, und somit eine bessere ersetzt durch ==
(für Puristen: ja ich kenne null
).
Das Problem ist, dass Sie sogar Arrays.equals(array1, array2)
hart gebissen werden, wenn Elemente des Arrays nicht equals
richtig implementiert werden. Ich weiß, es ist eine sehr naive Aussage, aber es gibt einen sehr wichtigen, weniger offensichtlichen Fall: Betrachten Sie ein 2D-Array.
2D-Array in Java ist ein Array von Arrays und Arrays ' equals
sind defekt (oder nutzlos, wenn Sie dies bevorzugen), sodass Arrays.equals(array1, array2)
sie bei 2D-Arrays nicht wie erwartet funktionieren.
Hoffentlich hilft das.
equals()
? Ich dachte, es wurde nicht von Object überschrieben.
Arrays.deepEquals
--- es ist das, was someArray.equals
die ganze Zeit hätte tun sollen. (Siehe auch : Objects.deepEquals
.)
Schauen Sie sich die Implementierung der beiden Methoden an, um sie genau zu verstehen:
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);
}
während:
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;
}
Seufzer. In den 70er Jahren war ich der "Systemprogrammierer" (sysadmin) für ein IBM 370-System, und mein Arbeitgeber war Mitglied der IBM-Benutzergruppe SHARE. Es kam manchmal vor, dass jemand einen APAR (Fehlerbericht) über ein unerwartetes Verhalten eines CMS-Befehls übermittelte und IBM auf NOTABUG antwortete: Der Befehl macht das, wofür er entwickelt wurde (und was in der Dokumentation steht).
SHARE hat sich einen Zähler dafür ausgedacht: BAD - Broken As Designed. Ich denke, dies könnte für diese Implementierung von Equals for Arrays gelten.
An der Implementierung von Object.equals ist nichts auszusetzen. Das Objekt hat keine Datenelemente, daher gibt es nichts zu vergleichen. Zwei "Objekte" sind genau dann gleich, wenn sie tatsächlich dasselbe Objekt sind (intern dieselbe Adresse und Länge).
Diese Logik gilt jedoch nicht für Arrays. Arrays haben Daten, und Sie erwarten einen Vergleich (über Gleichheit), um die Daten zu vergleichen. Idealerweise so wie Arrays.deepEquals, aber zumindest so wie Arrays.equals (flacher Vergleich der Elemente).
Das Problem ist also, dass das Array (als integriertes Objekt) Object.equals nicht überschreibt. String (als benannte Klasse) tut überschreiben Object.equals und geben Sie das Ergebnis Sie erwarten.
Andere Antworten sind richtig: [...]. Equals ([....]) vergleicht einfach die Zeiger und nicht den Inhalt. Vielleicht wird irgendwann jemand das korrigieren. Oder vielleicht auch nicht: Wie viele bestehende Programme würden kaputt gehen, wenn [...] tatsächlich die Elemente verglichen würden? Ich vermute, nicht viele, aber mehr als null.
Arrays erben equals()
von Object
und vergleichen daher nur true, wenn ein Array mit sich selbst verglichen wird.
Arrays.equals
Vergleicht andererseits die Elemente der Arrays.
Dieses Snippet verdeutlicht den Unterschied:
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
Siehe auch Arrays.equals()
. Eine andere statische Methode kann ebenfalls von Interesse sein : Arrays.deepEquals()
.
Die Arrays.equals(array1, array2)
:
Überprüfen Sie, ob beide Arrays die gleiche Anzahl von Elementen enthalten und alle entsprechenden Elementpaare in den beiden Arrays gleich sind.
Die array1.equals(array2)
:
Vergleichen Sie das Objekt mit einem anderen Objekt und geben Sie nur dann true zurück, wenn die Referenz der beiden Objekte gleich ist wie in der Object.equals()
Das equals()
von Arrays wird von geerbt Object
, sodass es nicht den Inhalt der Arrays betrachtet, sondern nur jedes Array als gleich betrachtet.
Die Arrays.equals()
Methoden haben die Arrays' Inhalte vergleichen. Es gibt Überladungen für alle primitiven Typen, und die für Objekte verwendet die eigenen equals()
Methoden der Objekte .
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));
}
}
Hier ist die Ausgabe:
array1 and array2 equal: false
array1 and array2 equal: false
array1 and array3 equal: true
array1 and array3 equal: false
Wenn ich diese Art von Problem sehe, würde ich mich persönlich für Arrays.equals(array1, array2)
Ihre Frage entscheiden, um Verwirrung zu vermeiden.