JavaRush /Blog Java /Random-MS /Equals in Java and String compare - Perbandingan rentetan...

Equals in Java and String compare - Perbandingan rentetan

Diterbitkan dalam kumpulan
hello! Hari ini kita akan bercakap tentang topik yang sangat penting dan menarik, iaitu, membandingkan objek antara satu sama lain equals() dalam Java. Dan sememangnya, dalam kes apa di Jawa Object A akan sama dengan Object B ? Perbandingan sama dan rentetan - 1Mari cuba tulis contoh:
public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {

       Car car1 = new Car();
       car1.model = "Ferrari";
       car1.maxSpeed = 300;

       Car car2 = new Car();
       car2.model = "Ferrari";
       car2.maxSpeed = 300;

       System.out.println(car1 == car2);
   }
}
Output konsol:

false
Okay, berhenti. Mengapa, sebenarnya, kedua-dua kereta ini tidak sama? Kami memberi mereka sifat yang sama, tetapi hasil perbandingan adalah palsu. Jawapannya mudah sahaja. Operator ==membandingkan bukan sifat objek, tetapi pautan. Walaupun dua objek mempunyai 500 sifat yang sama, hasil perbandingan akan tetap palsu. Lagipun, pautan car1menghala car2 ke dua objek berbeza , ke dua alamat berbeza. Bayangkan situasi dengan membandingkan orang. Mungkin ada orang di dunia ini yang mempunyai nama yang sama, warna mata, umur, ketinggian, warna rambut dan lain-lain dengan anda. Iaitu, anda serupa dalam banyak cara, tetapi anda masih bukan kembar, dan terutamanya bukan orang yang sama. Persamaan dan perbandingan rentetan - 2Operator menggunakan kira-kira logik yang sama ==apabila kita menggunakannya untuk membandingkan dua objek. Tetapi bagaimana jika anda memerlukan logik yang berbeza dalam program anda? Contohnya, jika program anda meniru analisis DNA. Dia mesti membandingkan kod DNA dua orang dan menentukan bahawa mereka adalah kembar.
public class Man {

   int dnaCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = 1111222233;

       Man man2 = new Man();
       man2.dnaCode = 1111222233;

       System.out.println(man1 == man2);
   }
}
Output konsol:

false
Adalah logik bahawa hasilnya adalah sama (lagipun, kami tidak mengubah apa-apa), tetapi sekarang kami tidak berpuas hati dengannya! Sememangnya, dalam kehidupan sebenar, analisis DNA adalah jaminan seratus peratus bahawa kita menghadapi kembar. Tetapi program dan pengendali kami ==memberitahu kami sebaliknya. Bagaimanakah kita boleh mengubah tingkah laku ini dan memastikan bahawa jika ujian DNA sepadan, program akan menghasilkan keputusan yang betul? Untuk tujuan ini, kaedah khas telah dicipta dalam Java - equals() .

Kaedah Equals() dalam Java

Seperti kaedah toString()yang kita bincangkan sebelum ini, equals() tergolong dalam kelas, Objectkelas yang paling penting dalam Java, dari mana semua kelas lain diperoleh. Walau bagaimanapun, equals() itu sendiri tidak akan mengubah tingkah laku program kami dalam apa jua cara:
public class Man {

   String dnaCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = "111122223333";

       Man man2 = new Man();
       man2.dnaCode = "111122223333";

       System.out.println(man1.equals(man2));
   }
}
Output konsol:

false
Keputusan yang sama, jadi mengapa kaedah ini diperlukan? :/ Mudah sahaja. Hakikatnya kini kami menggunakan kaedah ini kerana ia dilaksanakan dalam kelas itu sendiri Object. Dan jika kita pergi ke kod kelas Objectdan melihat bagaimana kaedah ini dilaksanakan di dalamnya dan apa yang dilakukannya, kita akan melihat:
public boolean equals(Object obj) {
   return (this == obj);
}
Inilah sebab mengapa tingkah laku program kami tidak berubah! Di dalam kaedah equals() kelas Objectterdapat perbandingan rujukan yang sama, ==. Tetapi helah kaedah ini ialah kita boleh mengatasinya. Mengatasi bermakna menulis kaedah equals() anda sendiri dalam kelas kami Mandan menjadikannya berkelakuan seperti yang kami mahu! Sekarang kami tidak berpuas hati bahawa cek itu man1.equals(man2)pada dasarnya melakukan perkara yang sama seperti man1 == man2. Inilah yang akan kami lakukan dalam situasi ini:
public class Man {

   int dnaCode;

   public boolean equals(Man man) {
       return this.dnaCode ==  man.dnaCode;
   }

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = 1111222233;

       Man man2 = new Man();
       man2.dnaCode = 1111222233;

       System.out.println(man1.equals(man2));

   }
}
Output konsol:

true
Hasil yang sama sekali berbeza! Dengan menulis kaedah equals() kami sendiri dan bukannya kaedah standard, kami mencapai tingkah laku yang betul: kini jika dua orang mempunyai kod DNA yang sama, program ini memberitahu kami: "Analisis DNA menunjukkan bahawa mereka adalah kembar" dan kembali benar! Dengan mengatasi kaedah equals() dalam kelas anda, anda boleh mencipta logik perbandingan objek yang diperlukan dengan mudah. Kami telah menyentuh tentang perbandingan objek hanya dari segi umum. Kami masih akan mengadakan kuliah besar yang berasingan mengenai topik ini di hadapan (anda boleh membacanya dengan cepat sekarang, jika anda berminat).

Perbandingan rentetan dalam Java - Perbandingan rentetan

Mengapa kita merawat perbandingan rentetan secara berasingan daripada semua yang lain? Sebenarnya, baris dalam pengaturcaraan adalah cerita yang berbeza. Pertama, jika anda mengambil semua program Java yang ditulis oleh manusia, kira-kira 25% daripada objek di dalamnya terdiri daripada mereka. Oleh itu, topik ini sangat penting. Kedua, proses membandingkan rentetan benar-benar berbeza daripada objek lain. Mari lihat contoh mudah:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
Output konsol:

false
Tetapi mengapa palsu? Barisnya betul-betul sama, perkataan demi perkataan :/ Anda boleh menganggap: ini kerana pengendali == membandingkan rujukan! Lagipun, s1mereka s2mempunyai alamat yang berbeza dalam ingatan. Jika pemikiran ini berlaku kepada anda, maka mari kita buat semula contoh kami:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush is the best site to learn Java!";
       System.out.println(s1 == s2);
   }
}
Kini kami juga mempunyai dua pautan, tetapi hasilnya telah berubah kepada sebaliknya: Output konsol:

true
keliru sepenuhnya? :) Mari kita fikirkan. Operator ==sebenarnya membandingkan alamat dalam ingatan. Peraturan ini sentiasa berfungsi dan tidak perlu meraguinya. Ini bermakna jika s1 == s2ia kembali benar, kedua-dua rentetan ini mempunyai alamat yang sama dalam ingatan. Dan memang betul! Sudah tiba masanya untuk berkenalan dengan kawasan memori khas untuk menyimpan rentetan - kolam rentetan ( String pool) Sama dan perbandingan rentetan - 3Kolam rentetan ialah kawasan untuk menyimpan semua nilai rentetan yang anda buat dalam program anda. Untuk apa ia dicipta? Seperti yang dinyatakan sebelum ini, rentetan mengambil sebahagian besar daripada semua objek. Dalam mana-mana program besar, banyak baris dicipta. Untuk menjimatkan memori, inilah yang diperlukan String Pool- satu baris dengan teks yang anda perlukan diletakkan di sana, dan pada masa hadapan, pautan yang baru dibuat merujuk kepada kawasan memori yang sama, tidak perlu memperuntukkan memori tambahan setiap kali. Setiap kali anda menulis String = “........”, program menyemak sama ada terdapat baris dengan teks sedemikian dalam kolam rentetan. Jika ada, yang baru tidak akan dibuat. Dan pautan baharu akan menghala ke alamat yang sama dalam kolam rentetan tempat rentetan ini disimpan. Oleh itu, apabila kita menulis dalam program
String s1 = "JavaRush is the best site to learn Java!";
String s2 = "JavaRush is the best site to learn Java!";
pautan s2menghala tepat ke tempat yang sama dengan s1. Perintah pertama mencipta baris baharu dalam kolam rentetan dengan teks yang kami perlukan, dan apabila sampai ke yang kedua, ia hanya merujuk kepada kawasan memori yang sama seperti s1. Anda boleh membuat sekurang-kurangnya 500 baris lagi dengan teks yang sama, hasilnya tidak akan berubah. Berhenti. Tetapi mengapa contoh ini tidak berkesan untuk kita lebih awal?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
Saya fikir, secara intuitif, anda sudah meneka apa sebabnya :) Cuba teka sebelum membaca lebih lanjut. Anda dapat melihat bahawa kedua-dua baris ini dicipta secara berbeza. Satu dengan bantuan operator new, dan yang kedua tanpanya. Inilah sebabnya. Operator baharu, apabila mencipta objek, secara paksa memperuntukkan kawasan baharu dalam ingatan untuknya . Dan baris yang dicipta dengan new, tidak berakhir dengan String Pool: ia menjadi objek yang berasingan, walaupun teksnya betul-betul sama dengan baris yang sama dari String Pool'a. Iaitu, jika kita menulis kod berikut:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush is the best site to learn Java!";
       String s3 = new String("JavaRush is the best site to learn Java!");
   }
}
Dalam ingatan ia akan kelihatan seperti ini: Sama dan perbandingan rentetan - 4Dan setiap kali objek baharu dicipta, newkawasan baharu akan diperuntukkan dalam ingatan, walaupun teks di dalam baris baharu adalah sama! Kami nampaknya telah menyelesaikan operator ==, tetapi bagaimana dengan rakan baru kami - kaedah equals()?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1.equals(s2));
   }
}
Output konsol:

true
Menarik. Kami tahu dengan tepat apa s1dan s2menunjukkan kawasan yang berbeza dalam ingatan. Tetapi, bagaimanapun, kaedah equals() mengatakan bahawa mereka adalah sama. kenapa? Ingat, di atas kami berkata bahawa kaedah equals() boleh ditindih dalam kelas anda supaya ia membandingkan objek seperti yang anda perlukan? Itulah yang mereka lakukan dengan kelas String. Ia mempunyai kaedah equals() yang ditindih. Dan ia bukan membandingkan pautan, melainkan urutan aksara dalam rentetan. Dan jika teks dalam rentetan adalah sama, tidak kira bagaimana ia dicipta dan di mana ia disimpan: dalam kolam rentetan, atau dalam kawasan memori yang berasingan. Hasil perbandingan akan menjadi benar. Ngomong-ngomong, Java membolehkan anda membandingkan rentetan dengan betul dalam cara yang tidak peka huruf besar-besaran. Dalam situasi biasa, jika anda menulis salah satu baris, contohnya, dalam huruf besar, hasil perbandingan akan menjadi palsu:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JAVARUSH - ЛУЧШИЙ САЙТ ДЛЯ ИЗУЧЕНИЯ JAVA!");
       System.out.println(s1.equals(s2));
   }
}
Output konsol:

false
Untuk kes ini, kelas Stringmempunyai kaedah equalsIgnoreCase(). Jika perkara utama dalam perbandingan anda ialah urutan aksara tertentu, dan bukan kes mereka, anda boleh menggunakannya. Sebagai contoh, ini berguna apabila membandingkan dua alamat e-mel:
public class Main {

   public static void main(String[] args) {

       String address1 = "Moscow, Academician Korolev street, 12";
       String address2 = new String("Г. МОСКВА, УЛ. АКАДЕМИКА КОРОЛЕВА, ДОМ 12");
       System.out.println(address1.equalsIgnoreCase(address2));
   }
}
Dalam kes ini, jelas bahawa kita bercakap tentang alamat yang sama, jadi menggunakan kaedah itu equalsIgnoreCase()akan menjadi keputusan yang tepat.

Kaedah String.intern().

Kelas Stringmempunyai kaedah rumit lain - intern(); Kaedah ini intern()berfungsi secara langsung dengan String Pool'om. Jika anda memanggil kaedah intern()pada rentetan, ia:
  • Melihat untuk melihat sama ada terdapat rentetan dengan teks ini dalam kolam rentetan
  • Jika ada, kembalikan pautan kepadanya di kolam
  • Jika tidak, ia meletakkan baris dengan teks ini dalam kolam rentetan dan mengembalikan pautan kepadanya.
Dengan menggunakan kaedah intern()pada rujukan rentetan yang dicipta melalui baharu, kita boleh membandingkannya dengan rujukan rentetan daripada String Pool'a melalui ==.
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2.intern());
   }
}
Output konsol:

true
Sebelum ini, apabila kita membandingkannya tanpa intern(), hasilnya adalah palsu. Sekarang kaedah itu intern()menyemak sama ada terdapat baris dengan teks "JavaRush - tapak terbaik untuk belajar Java!" dalam kolam rentetan. Sudah tentu ia ada: kami menciptanya apabila kami menulis
String s1 = "JavaRush is the best site to learn Java!";
Ia telah disemak bahawa rujukan s1dan rujukan yang dikembalikan oleh kaedah s2.intern()menghala ke kawasan yang sama dalam ingatan, dan, sudah tentu, mereka lakukan :) Untuk meringkaskan, mengingati dan menggunakan peraturan utama: Untuk membandingkan rentetan, SENTIASA gunakan equals() kaedah! Apabila membandingkan rentetan, anda hampir selalu bermaksud membandingkan teks mereka, bukan rujukan, kawasan memori dan sebagainya. Kaedah equals() melakukan apa yang anda perlukan. Berikut adalah beberapa pautan untuk anda belajar sendiri:
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION