bandingkanTo () vs. sama dengan ()

118

Saat menguji persamaan Stringdi Jawa, saya selalu menggunakan equals()karena bagi saya ini sepertinya metode paling alami untuk itu. Bagaimanapun, namanya sudah mengatakan apa yang akan dilakukannya. Namun, seorang kolega saya baru-baru ini memberi tahu saya telah diajari untuk menggunakan, compareTo() == 0bukan equals(). Ini terasa tidak wajar (seperti compareTo()yang dimaksudkan untuk memberikan tatanan dan tidak membandingkan kesetaraan) dan bahkan agak berbahaya (karena compareTo() == 0tidak selalu berarti kesetaraan dalam semua kasus, meskipun saya tahu itu untuk String) bagi saya.

Dia tidak tahu mengapa dia diajari untuk menggunakan compareTo()daripada equals()untuk String, dan saya juga tidak dapat menemukan alasan mengapa. Apakah ini benar-benar masalah selera pribadi, atau adakah alasan nyata untuk kedua metode tersebut?

Thomas Lötzer
sumber
9
Sebenarnya pada tingkat pengoptimalan mikro, yang seharusnya tidak pernah kita bicarakan secara prematur, .equalsIgnoreCase()adalah perbandingan tercepat jika memang sesuai, jika .equals()tidak itulah yang Anda inginkan.
1
Ini adalah pertanyaan lama, tapi mengandung nugget yang ingin saya tekankan: " compareTo() == 0tidak selalu berarti kesetaraan dalam semua kasus". Ini sangat benar! Persis seperti inilah arti frasa "konsisten dengan sama" dalam spesifikasi Java API, misalnya dalam spesifikasi kelas yang sebanding . Misalnya, metode perbandingan String konsisten dengan sama, tetapi metode perbandingan BigDecimal tidak konsisten dengan sama.
Stuart Marks

Jawaban:

105

Perbedaannya adalah bahwa "foo".equals((String)null)mengembalikan nilai salah saat "foo".compareTo((String)null) == 0melontarkan NullPointerException. Jadi mereka tidak selalu dapat dipertukarkan bahkan untuk String.

waxwing
sumber
6
Saya pikir Anda juga harus menyebutkan ini. sama dengan menghitung kode hash. Kode hash dari dua string berbeda, meskipun jarang, bisa jadi sama. Tapi saat menggunakan bandingkanTo (), itu memeriksa string karakter demi karakter. Jadi dalam kasus ini dua string akan mengembalikan nilai true jika dan hanya jika konten sebenarnya sama.
Ashwin
30
Menurut Anda mengapa itu sama dengan menghitung kode hash? Anda dapat melihat bahwa ini bukan masalahnya: docjar.com/html/api/java/lang/String.java.html (baris 1013).
waxwing
3
kamu benar. Saya pikir sama dan kode hash berjalan seiring (sama dengan memeriksa apakah keduanya memiliki kode hash yang sama). Lalu mengapa perlu untuk mengganti kedua metode ini jika Anda memutuskan untuk menimpa salah satunya.
Ashwin
3
Perlu untuk mengganti kode hash ketika kita mengganti sama karena jika kelas menggunakan koleksi berbasis hash, termasuk HashMap, HashSet, dan Hashtable kelas tidak akan berfungsi dengan baik
varunthacker
4
@Ashwin Hal ini diperlukan karena jika .equals mengembalikan nilai true, kode hash juga harus sama. Namun jika kode hash sama, itu tidak berarti .equals harus mengembalikan nilai true
Alan
33

2 perbedaan utamanya adalah:

  1. equalsakan mengambil Objek sebagai parameter, tetapi compareTohanya akan mengambil String.
  2. equalshanya memberi tahu Anda apakah keduanya sama atau tidak, tetapi compareTomemberikan informasi tentang bagaimana String dibandingkan secara leksikografis.

Saya melihat kode kelas String , dan algoritme di dalam bandingkanTo dan sama dengan pada dasarnya terlihat sama. Saya percaya pendapatnya hanya masalah selera, dan saya setuju dengan Anda - jika yang perlu Anda ketahui hanyalah persamaan String dan bukan yang mana yang lebih dulu secara leksikografis, maka saya akan menggunakan equals.

Kaleb Brasee
sumber
26

Saat membandingkan kesetaraan, Anda harus menggunakan equals(), karena ini mengungkapkan maksud Anda dengan cara yang jelas.

compareTo()memiliki kelemahan tambahan yaitu hanya bekerja pada objek yang mengimplementasikan Comparableantarmuka.

Ini berlaku secara umum, tidak hanya untuk String.

starblue
sumber
18

compareTotelah melakukan lebih banyak pekerjaan jika string memiliki panjang yang berbeda. equalsdapat kembali salah, sementara compareToharus selalu memeriksa karakter yang cukup untuk menemukan urutan penyortiran.

robinr
sumber
10

compareTo()tidak hanya berlaku untuk String tetapi juga objek lain karena compareTo<T>mengambil argumen umum T. String adalah salah satu kelas yang telah mengimplementasikan compareTo()metode dengan mengimplementasikan Comparableantarmuka. (bandingkanTo () adalah metode untuk Antarmuka yang sebanding). Jadi setiap kelas bebas mengimplementasikan antarmuka Comparable.

Tetapi compareTo()memberikan urutan objek , biasanya digunakan dalam mengurutkan objek dalam urutan naik atau turun sementara equals()hanya akan berbicara tentang persamaan dan mengatakan apakah mereka sama atau tidak.

apurva jadhav
sumber
10

Dalam Konteks String:
bandingkanTo: Membandingkan dua string secara leksikografis.
sama dengan: Membandingkan string ini dengan objek yang ditentukan.

bandingkanTo membandingkan dua string dengan karakternya (pada indeks yang sama) dan mengembalikan integer (positif atau negatif) yang sesuai.

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

equals () bisa lebih efisien daripada bandingkanTo () .

Perbedaan yang sangat penting antara bandingkanTo dan sama dengan:

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

equals () memeriksa apakah dua objek sama atau tidak dan mengembalikan boolean.

bandingkanTo () (dari interface Comparable) mengembalikan integer. Ia memeriksa mana dari dua objek yang "kurang dari", "sama dengan" atau "lebih besar dari" yang lain. Tidak semua objek bisa diurutkan secara logis, jadi metode bandingkanTo () tidak selalu masuk akal.

Perhatikan bahwa equals () tidak mendefinisikan pengurutan antar objek, seperti yang dilakukan oleh bandingkanTo ().

Sekarang saya menyarankan Anda untuk meninjau kode sumber dari kedua metode untuk menyimpulkan bahwa yang sama lebih disukai daripada bandingkan yang melibatkan beberapa perhitungan Matematika.

Jaimin Patel
sumber
5

Tampaknya kedua metode cukup banyak melakukan hal yang sama, tetapi metode bandingkanTo () mengambil String, bukan Objek, dan menambahkan beberapa fungsionalitas tambahan di atas metode equals () normal. Jika yang Anda pedulikan hanyalah persamaan, maka metode equals () adalah pilihan terbaik, karena lebih masuk akal bagi programmer berikutnya yang melihat kode Anda. Perbedaan waktu antara dua fungsi berbeda seharusnya tidak menjadi masalah kecuali Anda mengulang beberapa item dalam jumlah besar. CompareTo () sangat berguna ketika Anda perlu mengetahui urutan String dalam sebuah koleksi atau ketika Anda perlu mengetahui perbedaan panjang antara string yang dimulai dengan urutan karakter yang sama.

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

Scott M.
sumber
5

equals() harus menjadi metode pilihan dalam kasus OP.

Melihat implementasi equals()dan compareTo()di java.lang.String pada grepcode , kita dapat dengan mudah melihat bahwa persamaan lebih baik jika kita hanya mementingkan persamaan dua String:

equals():

1012   public  boolean sama dengan ( Object anObject) { 
1013 if ( this == anObject) {
1014 return true ;
1015 }
1016 if (anObject instanceof String ) {
1017 String anotherString = ( String ) anObject;
1018 int n = hitung;
1019 jika (n == anotherString.count) {
1020 char v1 [] = nilai;
1021 char v2 [] = anotherString.value;
1022 inti = offset;
1023 int j = anotherString.offset;
1024 sementara (n--! = 0) {
1025 if (v1 [i ++]! = V2 [j ++])
1026 return false ;
1027 }
1028 mengembalikan true ;
1029 }
1030 }
1031 return false ;
1032 }

dan compareTo():

1174   public  int bandingkanTo ( String anotherString) { 
1175 int len1 = count;
1176 int len2 = anotherString.count;
1177 int n = Matematika. min (len1, len2);
1178 char v1 [] = nilai;
1.179 char v2 [] = anotherString.value;
1180 int i = offset;
1181 int j = anotherString.offset;
1183 jika (i == j) {
1184 int k = i;
1185 int lim = n + i;
1186 sementara (k <lim) {
1187 karakter c1 = v1 [k];
1188 karakter c2 = v2 [k];
1189 if (c1! = C2) {
1190 return c1 - c2;
1191 }
1192 k ++;
1193 }
1194 } lain {
1195 sementara (n--! = 0) {
1196 char c1 = v1 [i ++];
1197 karakter c2 = v2 [j ++];
1198 if (c1! = C2) {
1199 return c1 - c2;
1200 }
1201 }
1202 }
1203 kembali len1 - len2;
1204 }

Ketika salah satu string adalah awalan dari string lain, kinerja dari compareTo()lebih buruk karena masih perlu menentukan urutan leksikografis sementara equals()tidak perlu khawatir lagi dan segera mengembalikan salah.

Menurut pendapat saya, kita harus menggunakan keduanya sebagaimana mestinya:

  • equals() untuk memeriksa kesetaraan, dan
  • compareTo() untuk menemukan urutan leksikal.
prk
sumber
3

equals () memeriksa apakah dua string sama atau tidak. Ini memberikan nilai boolean. bandingkanTo () memeriksa apakah objek string sama dengan, lebih besar atau lebih kecil dari objek string lainnya, memberikan hasil sebagai: 1 jika objek string lebih besar 0 jika keduanya sama -1 jika string lebih kecil dari string lain

persamaan:

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
Ankit Uniyal
sumber
2

Ini adalah percobaan di necromancy :-)

Sebagian besar jawaban membandingkan kinerja dan perbedaan API. Mereka kehilangan poin fundamental bahwa kedua operasi tersebut memiliki semantik yang berbeda.

Intuisi Anda benar. x.equals (y) tidak dapat dipertukarkan dengan x.compareTo (y) == 0. Yang pertama membandingkan identitas, sedangkan yang lain membandingkan pengertian 'size'. Memang benar bahwa dalam banyak kasus, terutama dengan tipe primitif, kedua hal ini sejajar.

Kasus umumnya adalah ini:

Jika x dan y identik, mereka berbagi 'ukuran' yang sama: jika x.equals (y) adalah benar => x.compareTo (y) adalah 0.

Namun, jika x dan y memiliki ukuran yang sama, bukan berarti keduanya identik.

jika x.compareTo (y) adalah 0 tidak selalu berarti x.equals (y) benar.

Contoh menarik di mana identitas berbeda dari ukuran adalah bilangan kompleks. Asumsikan bahwa perbandingan dilakukan dengan nilai absolutnya. Jadi diberikan dua bilangan kompleks: Z1 = a1 + b1 * i dan Z2 = a2 + b2 * i:

Z1.equals (z2) mengembalikan nilai true jika dan hanya jika a1 = a2 dan b1 = b2.

Namun Z1.compareTo (Z2) mengembalikan 0 untuk dan jumlah tak terbatas dari pasangan (a1, b1) dan (a2, b2) asalkan memenuhi kondisi a1 ^ 2 + b1 ^ 2 == a2 ^ 2 + b2 ^ 2.

Vitaliy
sumber
1
x.equals (y) bukan berarti Identity, tapi Equality. Identitas dibandingkan menggunakan x == y untuk tipe yang ditentukan pengguna di Java.
Fernando Pelliccioni
2

Hasil yang sama bisa lebih efisien daripada bandingkan

Jika panjang urutan karakter dalam String tidak cocok, tidak mungkin String sama sehingga penolakan bisa lebih cepat.

Apalagi jika itu objek yang sama (persamaan identitas daripada persamaan logis), itu juga akan lebih efisien.

Jika mereka juga menerapkan cache hashCode, bisa jadi lebih cepat untuk menolak yang tidak sama jika kode hash mereka tidak cocok.

Gopal Rajpurohit
sumber
2

String.equals()membutuhkan instanceofoperator memanggil sementara compareTo()tidak membutuhkan. Rekan saya telah mencatat penurunan kinerja besar yang disebabkan oleh jumlah instanceofpanggilan yang berlebihan dalam equals()metode, namun pengujian saya terbukti compareTo()hanya sedikit lebih cepat.

Saya menggunakan, bagaimanapun, Java 1.6. Pada versi lain (atau vendor JDK lainnya) perbedaannya bisa lebih besar.

Pengujian tersebut membandingkan setiap string dalam 1000 array elemen, diulangi 10 kali.

Pelaut Danubian
sumber
1
Saya kira Anda pasti menggunakan string yang sangat pendek, semua panjang yang sama dan dengan keragaman tinggi pada karakter pertama untuk mendapatkan hasil di mana compareTo()lebih cepat daripada equals()? Tetapi untuk sebagian besar kumpulan data dunia nyata equals()jauh lebih cepat daripada compareTo() == 0. equals()bersinar jika string memiliki awalan yang sama tetapi panjangnya berbeda atau jika sebenarnya adalah objek yang sama.
x4u
Nah, pengujian saya melawan hipotesis bahwa instanceof adalah pembunuh kinerja, jadi stringnya memang pendek.
Danubian Sailor
Jika string Anda acak dan sebagian besar memiliki panjang yang berbeda, maka pilihan yang lebih jelas adalah metode equals () dibandingkan bandingkanTo () karena dalam sebagian besar kasus, string akan segera mengembalikan false jika panjangnya tidak sama.
Sactiw
1
  1. equalsdapat menggunakan Objek apa pun sebagai parameter, tetapi compareTohanya dapat menggunakan String.

  2. ketika cometo null, compareToakan mengeluarkan pengecualian

  3. ketika Anda ingin mengetahui di mana perbedaan itu terjadi, Anda dapat menggunakan compareTo.

Macan kecil
sumber
bandingkanTo dapat mengambil objek apa pun sebagai argumen. Seperti yang dikatakan @apurva jadhav di atas, perbandingan mengambil argumen umum. Jika Anda mengimplementasikan comaparable as Comparable <String>, Anda hanya diizinkan untuk menggunakan string.
Gaurav Kumar
1
  • equals: diperlukan untuk memeriksa kesetaraan dan membatasi duplikat. Banyak kelas Pustaka Java menggunakan ini jika mereka ingin menemukan duplikat. misalnya HashSet.add(ob1)hanya akan menambah jika itu tidak ada. Jadi jika Anda memperluas beberapa kelas seperti ini, timpa equals().

  • compareTo: diperlukan untuk memesan elemen. Sekali lagi untuk penyortiran stabil Anda memerlukan persamaan, jadi ada pengembalian 0.

Rute Dillip
sumber
0

Sama dengan -

1- Timpa metode GetHashCode untuk memungkinkan suatu tipe bekerja dengan benar dalam tabel hash.

2- Jangan melempar pengecualian dalam penerapan metode Setara. Sebagai gantinya, kembalikan false untuk argumen nol.

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.

Pemanggilan x.Equals (y) berturut-turut mengembalikan nilai yang sama selama objek yang direferensikan oleh x dan y tidak dimodifikasi.

x.Equals(null) returns false.

4- Untuk beberapa jenis objek, sebaiknya uji Persamaan untuk persamaan nilai daripada persamaan referensial. Implementasi Equals seperti itu mengembalikan nilai true jika dua objek memiliki nilai yang sama, meskipun keduanya bukan instance yang sama.

Sebagai contoh -

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

Keluaran: -

False
True

sementara bandingkanTo -

Membandingkan instance saat ini dengan objek lain berjenis sama dan mengembalikan integer yang menunjukkan apakah instance saat ini mendahului, mengikuti, atau terjadi pada posisi yang sama dalam urutan seperti objek lainnya.

Ia kembali -

Kurang dari nol - Contoh ini mendahului obj dalam urutan urutan. Nol - Contoh ini terjadi pada posisi yang sama dalam urutan seperti obj. Lebih besar dari nol - Contoh ini mengikuti obj dalam urutan pengurutan.

ArgumentException bisa muncul jika objek tidak berjenis sama dengan instance.

Misalnya Anda bisa berkunjung ke sini.

Jadi saya menyarankan lebih baik untuk menggunakan Equals sebagai pengganti bandingkanTo.

Prabhat Jain
sumber
Tidak ada GetHashCode()metode. Apakah yang Anda maksud hashCode()?
Marquis dari Lorne
0

"sama dengan" membandingkan objek dan mengembalikan benar atau salah dan "bandingkan dengan" mengembalikan 0 jika benar atau angka [> 0] atau [<0] jika salah di sini contohnya:

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

Hasil:

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

Dokumentasi Dibandingkan dengan: https://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html

Dokumentasi Sama Dengan: https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object)

David Hackro
sumber
0

Di sini satu hal penting saat menggunakan compareTo()over equals()yang compareToberfungsi untuk kelas yang mengimplementasikan antarmuka 'Comparable' jika tidak maka akan memunculkan file NullPointerException. Stringclass mengimplementasikan antarmuka Comparable sementara StringBuffertidak maka Anda dapat menggunakan "foo".compareTo("doo")di Stringobjek tetapi tidak di StringBufferObject.

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

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

Ini mencetak -2 dan salah

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

Ini mencetak 2 dan salah

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

Ini mencetak 0 dan benar

sama dengan mengembalikan boolean jika dan hanya jika kedua string cocok.

bandingkanTo dimaksudkan tidak hanya untuk mengetahui apakah keduanya cocok tetapi juga untuk mengetahui String mana yang lebih rendah dari yang lain, dan juga seberapa banyak, secara leksikografis. Ini sebagian besar digunakan saat menyortir dalam koleksi.

Deepak Selvakumar
sumber
-1

Saya percaya equalsdan equalsIgnoreCasemetode Stringpengembalian truedan falseyang berguna jika Anda ingin membandingkan nilai objek string, Tetapi dalam kasus penerapan compareTodan compareToIgnoreCasemetode mengembalikan nilai positif, negatif dan nol yang akan berguna dalam kasus penyortiran.

Prakhar Aditya
sumber