CompareTo () ile eşittir ()


118

StringJava'da eşitliği test ederken her zaman kullandım equals()çünkü bana göre bu en doğal yöntem gibi görünüyor. Sonuçta, adı zaten ne yapması gerektiğini söylüyor. Ancak, yakın zamanda bir meslektaşım bana compareTo() == 0bunun yerine kullanmanın öğretildiğini söyledi equals(). Bu bana doğal görünmüyor compareTo()(eşitlik için bir sıralama sağlamak ve karşılaştırmak değil) ve hatta biraz tehlikeli (çünkü compareTo() == 0her durumda eşitlik anlamına gelmiyor, bunun için olduğunu bilsem bile String).

Diye kullanmaya öğretildi neden bilmiyordu compareTo()yerine equals()ilişkin String'ler, ve ben de bir neden bulamadık. Bu gerçekten kişisel bir zevk meselesi mi, yoksa her iki yöntemin de gerçek bir nedeni var mı?


9
Asla vaktinden önce konuşmamamız gereken mikro optimizasyon düzeyinde, .equalsIgnoreCase()uygunsa en hızlı karşılaştırmadır, aksi takdirde .equals()istediğiniz şey budur.

1
Bu eski bir soru, ama vurgulamak istediğim bir külçe içeriyor: " compareTo() == 0her durumda eşitlik anlamına gelmez". Bu kesinlikle doğru! Java API belirtimlerinde, örneğin Karşılaştırılabilir sınıf belirtiminde "eşittir ile tutarlı" ifadesi tam olarak bu anlama gelir . Örneğin, String'in karşılaştırma yöntemi eşittir ile tutarlıdır, ancak BigDecimal'in karşılaştırma yöntemi eşittir ile tutarsızdır .
Stuart Marks

Yanıtlar:


105

Bir fark, bir NullPointerException "foo".equals((String)null)atarken false döndürmesidir "foo".compareTo((String)null) == 0. Bu nedenle, Dizeler için bile her zaman birbirinin yerine geçemezler.


6
Sanırım bundan da bahsetmelisiniz. equals, hashcode'u hesaplar. İki farklı dizenin karma kodu nadir de olsa aynı olabilir. Ancak CompareTo () kullanıldığında, dizeleri karakter karakter kontrol eder. Yani bu durumda iki dize ancak ve ancak gerçek içerikleri eşitse doğru döndürür.
Ashwin

30
Neden hashcode'u hesaplayan eşittir sanıyorsun? Durumun böyle olmadığını görebilirsiniz: docjar.com/html/api/java/lang/String.java.html (satır 1013).
ağda

3
Haklısın. Eşittir ve karma kodun el ele gittiğini düşündüm (eşittir, her ikisinin de aynı karma koduna sahip olup olmadığını kontrol eder). Öyleyse, bunlardan herhangi birini geçersiz kılmaya karar verirseniz, neden bu iki yöntemi de geçersiz kılmanız gerekir?
Ashwin

3
Eşitleri geçersiz kıldığımızda hashcode'u geçersiz kılmak gerekir çünkü sınıf HashMap, HashSet ve Hashtable dahil olmak üzere hash tabanlı koleksiyonlar kullanıyorsa, sınıf düzgün çalışmayacaktır
varunthacker

4
@Ashwin Bu gereklidir, çünkü .equals true döndürürse, hashcode'lar da eşit olmalıdır. Ancak, hashcodes eşitse bu, .equals değerinin doğru dönmesi gerektiği anlamına gelmez
Alan

33

2 ana fark şudur:

  1. equalsherhangi bir Nesneyi parametre olarak alır, ancak compareToyalnızca Dizeleri alır.
  2. equalssize yalnızca eşit olup olmadıklarını söyler, ancak compareToDizelerin sözlükbilimsel olarak nasıl karşılaştırıldığına dair bilgi verir.

String sınıf koduna bir göz attım ve CompareTo ve equals içindeki algoritma temelde aynı görünüyor. Onun fikrinin sadece bir zevk meselesi olduğuna inanıyorum ve size katılıyorum - eğer bilmeniz gereken tek şey Dizelerin eşitliği ise ve hangisinin sözlükbilimsel olarak önce geldiği değilse, o zaman kullanırdım equals.


26

Eşitlik için karşılaştırma yaparken kullanmalısınız equals(), çünkü amacınızı net bir şekilde ifade eder.

compareTo()sadece Comparablearayüzü uygulayan nesneler üzerinde çalışması gibi ek bir dezavantaja sahiptir .

Bu genel olarak yalnızca Dizeler için geçerli değildir.


18

compareTodizelerin farklı uzunlukları varsa daha fazla iş yapar. equalssadece yanlış döndürebilir, ancak compareTosıralama düzenini bulmak için her zaman yeterli karakteri incelemelidir.


10

compareTo()sadece Dizeler için değil, aynı zamanda diğer nesneler için de geçerlidir çünkü compareTo<T>genel bir argüman alır T. String, arayüzü compareTo()uygulayarak yöntemi uygulayan sınıflardan biridir Comparable. (CompareTo (), karşılaştırılabilir Arayüz için bir yöntemdir). Dolayısıyla, herhangi bir sınıf, Karşılaştırılabilir arayüzü uygulamakta özgürdür.

Ancak compareTo()nesnelerin sırasını verir, tipik olarak nesneleri artan veya azalan sırayla sıralamak için kullanılırken equals(), yalnızca eşitlikten bahsedecek ve eşit olup olmadıklarını söyleyecektir.


10

Dize Bağlamında:
CompareTo: İki dizeyi sözlükbilimsel olarak karşılaştırır.
eşittir: Bu dizeyi belirtilen nesneyle karşılaştırır.

CompareTo iki dizeyi karakterlerine göre (aynı dizinde) karşılaştırır ve buna göre bir tamsayı (pozitif veya negatif) döndürür.

String s1 = "ab";
String s2 = "ab";
String s3 = "qb";
s1.compareTo(s2); // is 0
s1.compareTo(s3); // is -16
s3.compareTo(s1); // is 16

7

equals () daha verimli olabilir ve daha sonra ComparTo () olabilir .

CompareTo ve equals arasında çok önemli bir fark:

"myString".compareTo(null);  //Throws java.lang.NullPointerException
"myString".equals(null);     //Returns false

equals () , iki nesnenin aynı olup olmadığını kontrol eder ve bir boole döndürür.

CompareTo () (Comparable arayüzünden) bir tamsayı döndürür. İki nesneden hangisinin diğerinden "küçük", "eşit" veya "büyük" olduğunu kontrol eder. Tüm nesneler mantıksal olarak sıralanamaz, bu nedenle bir CompareTo () yöntemi her zaman mantıklı değildir.

Equals () öğesinin nesneler arasındaki sıralamayı tanımlamadığını unutmayın;

Şimdi, eşittir seçeneğinin, bazı Matematik hesaplamalarını içerdiğine göre daha tercih edilebilir olduğu sonucuna varmak için her iki yöntemin kaynak kodunu incelemenizi tavsiye ederim.


5

Görünüşe göre her iki yöntem de hemen hemen aynı şeyi yapıyor, ancak CompareTo () yöntemi bir Object yerine bir String alır ve normal equals () yönteminin üzerine bazı ekstra işlevler ekler. Tek umursadığınız eşitlikse, equals () yöntemi en iyi seçimdir, çünkü kodunuza bakan bir sonraki programcı için daha mantıklıdır. İki farklı işlev arasındaki zaman farkı, bazı büyük miktarda öğe üzerinde döngü yapmadığınız sürece önemli olmamalıdır. CompareTo (), bir koleksiyondaki Dizelerin sırasını bilmeniz gerektiğinde veya aynı karakter dizisiyle başlayan dizeler arasındaki uzunluk farkını bilmeniz gerektiğinde gerçekten yararlıdır.

kaynak: http://java.sun.com/javase/6/docs/api/java/lang/String.html


5

equals() OP durumunda tercih edilen yöntem olmalıdır.

Uygulanmasına bakıldığında equals()ve compareTo()içinde grepcode üzerinde java.lang.String , kolayca sadece iki Strings eşitliği ile ilgili iseniz eşittir daha iyi olduğunu görebilirsiniz:

equals():

1012   public  boolean equals ( Object anObject) { 
1013 if ( this == anObject) {
1014 return true ;
1015 }
1016 , eğer (birNesne instanceof dize ) {
1017 Yaylı anotherString = ( string ) birNesne;
1018 int n = sayım;
1019 if (n == anotherString.count) {
1020 karakter v1 [] = değer;
1021 karakter v2 [] = otherString.value;
1022 inti = ofset;
1023 int j = otherString.offset;
1024 da (! N- = 0) {
1025 ise (v1 [i ++] = v2 [j ++]!)
1026 dönüş sahte ;
1027 }
1028 true döndürür ; 1029 } 1030 } 1031 dönüş sahte ; 1032 }




ve compareTo():

1174   public  int CompareTo ( String anotherString ) { 
1175 int len1 = count;
1176 int len2 = anotherString.count;
1177 int n = Matematik. min (len1, len2);
1178 karakter v1 [] = değer;
1179 karakter v2 [] = otherString.value;
1180 int i = ofset;
1181 int j = otherString.offset;
1183 eğer (i == j) {
1184 int k = i;
1185 int lim = n + i;
1186 while (k <lim) {
1187 karakter c1 = v1 [k];
1188 karakter c2 = v2 [k];
1189 eğer (c1! = C2) {
1190, c1 - c2 döndürür ;
1191 }
1192 k ++;
1193 }
1194 } başka {
1195 while (n--! = 0) {
1196 karakter c1 = v1 [i ++];
1197 karakter c2 = v2 [j ++];
1198 ise (c1 = c2!) {
1199 dönüş c1 - c2;
1200 }
1201 }
1202 }
1203 dönüş len1 - len2;
1204 }

Dizelerden biri diğerinin önekiyse, performansı compareTo()daha kötüdür çünkü sözlüksel sıralamayı belirlemesi gerekirken equals()artık endişelenmez ve hemen yanlış döndürür.

Bence bu ikisini amaçlandığı gibi kullanmalıyız:

  • equals() eşitliği kontrol etmek ve
  • compareTo() sözcüksel sıralamayı bulmak için.

3

equals (), iki dizenin eşit olup olmadığını kontrol eder ve boole değerini verir. CompareTo (), dize nesnesinin diğer dize nesnesine eşit, daha büyük veya daha küçük olup olmadığını kontrol eder. şu şekilde sonuç verir: 1 eğer dize nesnesi daha büyükse 0, eğer dize diğer dizeden küçükse -1 ise

eşdeğer:

String a = "Amit";
String b = "Sumit";
String c = new String("Amit");
System.out.println(a.equals(c));//true
System.out.println(a.compareTo(c)); //0
System.out.println(a.compareTo(b)); //1


2

Bu büyücülükte bir deney :-)

Çoğu yanıt, performansı ve API farklılıklarını karşılaştırır. İki işlemin farklı anlamlara sahip olduğu temel noktasını gözden kaçırıyorlar.

Sezginiz doğru. x.equals (y), x.compareTo (y) == 0 ile değiştirilemez. İlki kimliği, diğeri 'boyut' kavramını karşılaştırır. Çoğu durumda, özellikle ilkel türlerde, bu ikisinin birlikte hizalandığı doğrudur.

Genel durum şudur:

Eğer x ve y aynıysa, aynı 'boyutu' paylaşırlar: eğer x.equals (y) true ise => x.compareTo (y) 0'dır.

Ancak, x ve y aynı boyutu paylaşıyorsa, bu onların aynı oldukları anlamına gelmez.

x.compareTo (y) 0 ise, x.equals (y) 'nin doğru olduğu anlamına gelmez.

Kimliğin boyuttan farklı olduğu zorlayıcı bir örnek, karmaşık sayılar olacaktır. Karşılaştırmanın mutlak değerine göre yapıldığını varsayalım. İki karmaşık sayı verildiğinde: Z1 = a1 + b1 * i ve Z2 = a2 + b2 * i:

Z1.equals (z2), ancak ve ancak a1 = a2 ve b1 = b2 ise doğru döndürür.

Ancak, Z1.compareTo (Z2), a1 ^ 2 + b1 ^ 2 == a2 ^ 2 + b2 ^ 2 koşulunu sağladıkları sürece sonsuz sayıda (a1, b1) ve (a2, b2) çifti için 0 ve sonsuz sayıda döndürür.


1
x.equals (y) Özdeşlik anlamına gelmez, Eşitlik anlamına gelir. Kimlik, Java'da kullanıcı tanımlı türler için x == y kullanılarak karşılaştırılır.
Fernando Pelliccioni

2

Eşittir daha verimli olabilir ve daha sonra CompareTo

String'deki karakter dizilerinin uzunluğu eşleşmezse, Dizelerin eşit olması mümkün değildir, bu nedenle reddetme çok daha hızlı olabilir.

Üstelik eğer aynı nesne ise (mantıksal eşitlikten ziyade kimlik eşitliği), aynı zamanda daha verimli olacaktır.

Eğer hashCode önbelleğe almayı da uyguladılarsa, hashCode'larının eşleşmemesi durumunda eşit olmayanları reddetmek daha da hızlı olabilir.


2

String.equals()gerektirmezken instanceofoperatörü çağırmayı compareTo()gerektirir. Meslektaşım, yöntemdeki aşırı sayıda instanceofçağrının neden olduğu büyük performans düşüşünü kaydetti equals(), ancak testimin compareTo()yalnızca biraz daha hızlı olduğu kanıtlandı .

Ancak Java 1.6 kullanıyordum. Diğer sürümlerde (veya diğer JDK satıcılarında) fark daha büyük olabilir.

Test, 10 kez tekrarlanan 1000 öğe dizisindeki her bir dizeyi karşılaştırdı.


1
Sanırım compareTo()daha hızlı olan bir sonuç elde etmek için ilk karakterde hepsi aynı uzunlukta ve yüksek çeşitlilikte çok kısa dizeler kullanmış olmalısınız equals()? Ancak çoğu gerçek dünya verileri kümesi equals()için çok daha hızlıdır compareTo() == 0. equals()dizelerin ortak bir öneki ancak farklı uzunlukları varsa veya gerçekte aynı nesnelerse parlar.
x4u

Benim testim performans öldürücü hipoteze karşıydı, bu yüzden dizeler gerçekten kısaydı.
Danubian Sailor

Eğer dizginiz rastgele ise ve çoğunlukla farklı uzunlukta ise, o zaman daha açık olan seçim, çoğu durumda eşit uzunlukta değilse hemen false döndürdüğü için, daha açık olan, CompareTo () yerine eşittir () yöntemi olmalıdır.
sactiw

1
  1. equalsherhangi bir Nesneyi parametre olarak alabilir ancak compareToyalnızca String alabilir.

  2. null'a geldiğinde, compareTobir istisna atar

  3. farkın nerede olduğunu bilmek istediğinizde kullanabilirsiniz compareTo.


CompareTo herhangi bir nesneyi argüman olarak alabilir. @ Apurva jadhav'ın yukarıda söylediği gibi, karşılaştırılabilir genel bir argüman alır. Comaparable'ı Comparable <String> olarak uygularsanız, yalnızca dizeleri kullanmanıza izin verilir.
Gaurav Kumar

1
  • equals: eşitliği kontrol etmek ve kopyaları kısıtlamak için gereklidir. Çoğu Java Kitaplığı sınıfı, kopyaları bulmak istemeleri durumunda bunu kullanır. örneğin HashSet.add(ob1), yalnızca bu yoksa eklenir. Öyleyse, bunun gibi bazı sınıfları genişletiyorsanız, geçersiz kılın equals().

  • compareTo: eleman siparişi için gereklidir. Yine kararlı sıralama için eşitliğe ihtiyacınız var, yani bir getiri 0 var.


0

Eşittir -

1- Bir türün hash tablosunda düzgün çalışmasına izin vermek için GetHashCode yöntemini geçersiz kılın.

2- Eşittir yönteminin uygulanmasında bir istisna atmayın. Bunun yerine, boş bir bağımsız değişken için yanlış döndür.

3-

  x.Equals(x) returns true.

  x.Equals(y) returns the same value as y.Equals(x).

  (x.Equals(y) && y.Equals(z)) returns true if and only if x.Equals(z) returns true.

X.Equals (y) 'nin art arda çağrılması, x ve y tarafından başvurulan nesne değiştirilmediği sürece aynı değeri döndürür.

x.Equals(null) returns false.

4- Bazı nesneler için, referans eşitlik yerine değer eşitliği için Eşittir testi yapılması istenir. Eşittir'in bu tür uygulamaları, iki nesne, aynı örnek olmasa bile aynı değere sahipse doğru sonucunu döndürür.

Örneğin -

   Object obj1 = new Object();
   Object obj2 = new Object();
   Console.WriteLine(obj1.Equals(obj2));
   obj1 = obj2; 
   Console.WriteLine(obj1.Equals(obj2)); 

Çıktı :-

False
True

while CompareTo -

Geçerli örneği aynı türdeki başka bir nesneyle karşılaştırır ve geçerli örneğin diğer nesneyle sıralama düzeninde aynı konumda önde mi, sonra mı yoksa aynı konumda mı gerçekleştiğini gösteren bir tam sayı döndürür.

Dönüyor -

Sıfırdan küçük - Bu örnek, sıralama düzeninde obj'den önce gelir. Sıfır - Bu örnek, sıralama düzeninde obj ile aynı konumda bulunur. Sıfırdan büyük - Bu örnek, sıralama düzeninde obj'i izler.

Nesne, örnekle aynı türde değilse ArgumentException oluşturabilir.

Örneğin burayı ziyaret edebilirsiniz.

Bu nedenle, CompareTo yerine Eşittir'i kullanmayı öneriyorum.


GetHashCode()Yöntem yok . Şunu musunuz hashCode()?
Marquis of Lorne

0

"eşittir", nesneleri karşılaştırır ve doğru veya yanlış döndürür ve "karşılaştır" ile döndürür "doğruysa 0 veya bir sayı [> 0] veya yanlışsa [<0] burada bir örnek:

<!-- language: lang-java -->
//Objects Integer
Integer num1 = 1;
Integer num2 = 1;
//equal
System.out.println(num1.equals(num2));
System.out.println(num1.compareTo(num2));
//New Value
num2 = 3;//set value
//diferent
System.out.println(num1.equals(num2));
System.out.println(num1.compareTo(num2));

Sonuçlar:

num1.equals(num2) =true
num1.compareTo(num2) =0
num1.equals(num2) =false
num1.compareTo(num2) =-1

Belgeler Şununla karşılaştırın: https://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html

Belgeler Eşittir: https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object)


0

Kullanırken Burada bir şey önemlidir compareTo()üzerinde equals()olduğu compareTosınıflar için çalışmalar uygular 'Karşılaştırılabilir' arayüzü aksi takdirde atmak olacağını NullPointerException. Stringsınıflar uygular Karşılaştırılabilir arayüz süre StringBufferdolayısıyla kullanabileceğiniz gelmez "foo".compareTo("doo")de Stringnesne değil de StringBufferNesne.


0
String s1 = "a";
String s2 = "c";

System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));

Bu -2 ve yanlış yazdırır

String s1 = "c";
String s2 = "a";
System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));

Bu 2 ve yanlış yazdırır

String s1 = "c";
String s2 = "c";
System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));

Bu 0 yazdırır ve doğru

equals, yalnızca ve ancak her iki dizge de eşleşirse boole döndürür.

CompareTo, sadece eşleşip eşleşmediklerini değil, aynı zamanda hangi String'in diğerinden daha az olduğunu ve ayrıca sözlükbilimsel olarak ne kadar olduğunu söylemeyi amaçlamaktadır. Bu, çoğunlukla koleksiyonda sıralama yapılırken kullanılır.


-1

İnanıyorum equalsve equalsIgnoreCaseyöntemleri Stringdönüş trueve falsesen dize nesnesinin değerlerini karşılaştırmak istiyorsa yararlıdır hangi Ama uygulanmasında durumunda compareTove compareToIgnoreCasepozitif, negatif ve sıralama halinde faydalı olacaktır sıfır değerini yöntemleri döner.

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.