Java'ya eşittir Arrays.equals


209

Java'daki dizileri karşılaştırırken, aşağıdaki 2 ifade arasında herhangi bir fark var mı?

Object[] array1, array2;
array1.equals(array2);
Arrays.equals(array1, array2);

Ve eğer öyleyse, bunlar nedir?


([] A1, Nesne [] a2 Object) java.util.Arrays.deepEquals da bir göz atın
ultraon

Yanıtlar:


299

array1.equals(array2)ile aynıdır array1 == array2, yani aynı dizi. @Alf'ın işaret ettiği gibi çoğu insanın beklediği şey bu değildir.

Arrays.equals(array1, array2) Dizilerin içeriğini karşılaştırır.


Benzer şekilde array.toString()çok yararlı olmayabilir ve kullanmanız gerekir Arrays.toString(array).


59
Not Arrays.equals()boyutlu diziler için beklendiği gibi çalışmıyor, sadece referans eşitlik için 1 boyutun öğeleri karşılaştırır. Apache ArrayUtils.isEquals, çok boyutlu dizilerle çalışır.
Adam Parkin

4
Hayrete düştüm. Array.equals'ın uzunluk ve her nesneyi karşılaştırmak yerine işaretçi karşılaştırmasına uygulanması için bir neden var mı?
Göl

2
@Lake, dizi uzunluğunu ve içerdiği nesneleri karşılaştırır, ancak yapmadıkları derin bir karşılaştırmadır. Eşittir diziler için beklendiği gibi çalışıyor kırık, bu ilk etapta bir sorun olmamalı.
Peter Lawrey

48
@AdamParkin İşte bu yüzden var Arrays.deepEquals(Object[], Object[]).
Elliott Frisch

3
@JeewanthaSamaraweera, bu yöntemin tanımıdır, ancak .equalsbunun için içeriği karşılaştırmaz, bu yüzden bu yönteme ihtiyacınız vardır.
Peter Lawrey

86

Bu rezil bir sorun: .equals()çünkü diziler çok bozuk, sadece onu kullanmayın.

Bununla birlikte, "birisi gerçekten yanlış bir şekilde yaptı" da olduğu gibi "kırılmadı" - sadece tanımlananı yapıyor ve genellikle bekleneni yapmıyor. Yani saflar için: gayet iyi ve bu da asla kullanma.

Şimdi beklenen davranış equalsverileri karşılaştırmaktır. Varsayılan davranış, Objectherhangi bir veri içermediği için kimliği karşılaştırmaktır (puristler için: evet var, ama mesele değil); varsayım, equalsalt sınıflara ihtiyacınız varsa bunu uygulayacağınızdır. Dizilerde sizin için bir uygulama yoktur, bu yüzden onu kullanmanız gerekmez.

Fark, beklediğiniz gibiArrays.equals(array1, array2) çalışır (yani içeriği karşılaştırır), uygulamaya geri döner , bu da kimliği karşılaştırır ve böylece daha iyi değiştirilir (saflar için: evet biliyorum ).array1.equals(array2)Object.equals==null

Sorun, Arrays.equals(array1, array2)dizi elemanları equalsdüzgün uygulanmazsa bile sizi zor ısıracaktır . Bu çok naif bir ifade, biliyorum, ama çok daha az belirgin bir durum var: bir 2D dizi düşünün.

Java'daki 2B dizi bir dizi dizidir ve diziler equalsbozulur (veya tercih ederseniz işe yaramaz), bu nedenle Arrays.equals(array1, array2)2B dizilerde beklediğiniz gibi çalışmaz.

Umarım yardımcı olur.


13
Kırık değil, sadece Object'ten miras alındı.
Michael Borgwardt

Bir dizinin özel bir uygulaması var mı equals()? Object'ten geçersiz kılınmadığını düşündüm.
Martijn Courteaux

@ MichaelBorgwardt Javadoc'ta söylenenleri yapmayan bir yöntemle bir sistem kütüphanesi. Sesler bana yeterince kırıldı. Bununla birlikte, çok tartışmalı bir ifade olduğunu itiraf ediyorum, ancak "kırıldığının" daha iyi hatırlandığına inanıyorum ve bu yüzden bunu bu şekilde düşünmek çok daha uygun.
alf

Tam olarak sorun :) var @MartijnCourteaux
Alf

3
Dizilerin dizileri için ihtiyacınız olan Arrays.deepEquals--- başından beri someArray.equalsyapılması gereken şey budur. (İlgili Objects.deepEquals
Kevin J. Chase

16

Bunları derinlemesine anlamak için iki yöntemin uygulanmasına bakın:

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

süre:

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

11

İç çekmek. 70'lerde bir IBM 370 sistemi için "sistem programcısı" (sysadmin) ve işverenim, SHARE IBM kullanıcı grubunun bir üyesiydi. Bazen, bazı CMS komutlarının beklenmedik davranışları hakkında bir APAR (hata raporu) gönderir ve IBM NOTABUG yanıt verir: komut, yapmak için tasarlandığını (ve belgelerin söylediklerini) yapar.

PAYLAŞ buna bir sayaç getirdi: KÖTÜ - Tasarlandığı Gibi Kırık. Bence bu, diziler için eşit olan bu uygulama için geçerli olabilir.

Object.equals uygulamasının yanlış bir yanı yok. Nesnenin veri üyesi yok, bu yüzden karşılaştırılacak bir şey yok. İki "Nesne" eşit ve sadece aynı Nesne (dahili olarak aynı adres ve uzunluk) ise eşittir.

Ancak bu mantık diziler için geçerli değildir. Dizilerin verileri vardır ve verileri karşılaştırmak için (eşitlerle) karşılaştırmayı beklersiniz. İdeal olarak, Arrays.deepEquals'ın yaptığı gibi, ama en azından Arrays.equals'ın yaptığı gibi (öğelerin sığ karşılaştırması).

Sorun şu ki, dizi (yerleşik bir nesne olarak) Object.equals'ı geçersiz kılmaz. (Adlandırılmış sınıf olarak) Dize yapar geçersiz kılma Object.Equals ve beklediğiniz sonucu verir.

Verilen diğer cevaplar doğrudur: [...]. Eşittir ([....]) içeriği değil, işaretçileri karşılaştırır. Belki bir gün birisi bunu düzeltir. Ya da belki de: [...]. Öğeleri gerçekten karşılaştırırsa kaç tane programın kırılacağı? Çok değil, şüpheliyim ama sıfırdan fazla.


5
Broken.As.Designed kısaltmasını seviyorum
Chris

5

Diziler miras equals()alır Objectve dolayısıyla karşılaştırma yalnızca bir diziyi kendisiyle karşılaştırırsa true değerini döndürür.

Öte yandan, Arrays.equalsdizilerin elemanlarını karşılaştırır.

Bu pasaj farkı aydınlatır:

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

Ayrıca bakınız Arrays.equals(). Başka statik yöntem ayrıca ilgi olabilir: Arrays.deepEquals().


1

Arrays.equals(array1, array2):

her iki dizinin de aynı sayıda öğe içerip içermediğini ve iki dizideki karşılık gelen tüm öğe çiftlerinin eşit olup olmadığını kontrol edin.

array1.equals(array2):

nesneyi başka bir nesneyle karşılaştırın ve yalnızca iki nesnenin başvurusu, Object.equals()


0

equals()Dizilerin miras Objectbu arrrays içeriğine bakmaz, böylece, sadece her bir dizi kendisine eşit görmektedir.

Arrays.equals()Yöntemler do dizilerdeki içeriğini karşılaştırın. Tüm ilkel tipler için aşırı yüklenmeler vardır ve nesneler için olanı nesnelerin kendi equals()yöntemlerini kullanır .


2
"dizilerin içeriği" diyorsunuz, bu da çok boyutlu diziler anlamına mı geliyor?
AlanFoster

@AlanFoster: hayır. Çok boyutlu diziler dizilerin dizileridir, yani Arrays.equals (Object [], Object []) yöntemini çağırırlar, bu da alt dizilerin eşittir () yöntemlerini çağırır
Michael Borgwardt

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

   }
}

İşte çıktı:

    array1 and array2 equal: false
    array1 and array2 equal: false

    array1 and array3 equal: true
    array1 and array3 equal: false

Bu tür bir problem gördüğümde, Arrays.equals(array1, array2)kafa karışıklığını önlemek için kişisel olarak sorunuza göre giderdim .


Doğru gibi görünüyor, ancak dizilerde elemanların sırası da önemlidir. Örneğin, başka bir dizi varsa Object [] array4 = new Object [] {123, 1}; Arrays.equals (dizi3, dizi4) ile false değerini döndürür.
jiahao
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.