Kata pengantar
Ketika mengacu pada operasi perbandingan membandingkan "ukuran" dari dua objek saat melakukan algoritma seperti sortir penyisipan, jenis bukit, dan gabungan. Sangat mudah untuk memahami metode perbandingan integer i> j, tetapi ketika kita mengurutkan banyak objek, bagaimana kita membandingkan "ukuran" dua objek? Perbandingan Stu1> Stu2 seperti itu jelas tidak mungkin dikompilasi. Untuk memecahkan masalah cara membandingkan ukuran dua objek, JDK menyediakan dua antarmuka java.lang.Comparable dan java.util.Comparator .
1. Penyortiran Alami: java.lang.compparable
Hanya ada satu metode yang disediakan dalam antarmuka yang sebanding: compareTo(Object obj) , dan nilai pengembalian metode ini adalah int. Jika nilai pengembalian adalah angka positif, itu berarti bahwa objek saat ini (objek yang memanggil metode) lebih "lebih besar" daripada objek OBJ; Kalau tidak, itu "kecil"; Jika nol, itu berarti bahwa kedua objek itu sama.
Berikut adalah kelas siswa yang mengimplementasikan antarmuka yang sebanding:
siswa kelas publik mengimplementasikan {private int id; nama string pribadi; siswa publik () {super (); } @Override public int compareto (objek obj) {if (instance Obj dari siswa) {student stu = (siswa) obj; Return ID - Stu.id; } return 0; } @Override public string toString () {return "<" + id + "," + name + ">"; }} Siswa mengimplementasikan antarmuka penyortiran alami yang sebanding. Jadi bagaimana kita menggunakan antarmuka ini untuk mengurutkan satu set objek siswa? Ketika kami belajar array, kami menggunakan kelas untuk mengurutkan array integer: java.util.Arrays . Kami menggunakan metode sortir array untuk mengurutkan array integer. Setelah membalik -balik dokumentasi API, Anda akan menemukan bahwa array memberikan banyak bentuk kelebihan bentuk metode pengurutan, termasuk sort(Object[] obj) , yang berarti bahwa Arryas juga dapat mengurutkan array objek. Saat membandingkan "ukuran" dari dua objek selama proses penyortiran, antarmuka yang sebanding digunakan untuk membandingkan metode compareTo.
Public Class CompareTest {public static void main (string [] args) {student stu1 = siswa baru (1, "little"); Siswa Stu2 = Siswa Baru (2, "Cyntin"); Siswa Stu3 = Siswa Baru (3, "Tony"); Siswa Stu4 = Siswa Baru (4, "Gemini"); Siswa [] stus = siswa baru [4]; Stu0] = Stu1; Stu1 [1] = Stu4; Stus [2] = Stu3; Stu3] = Stu2; System.out.println ("Array:" + Arrays.tostring (STUS)); Arrays.sort (stus); System.out.println ("sort:" + arrays.tostring (stus)); }} Urutan di mana elemen ditambahkan dalam array siswa tidak ditambahkan sesuai dengan ID siswa. Setelah menelepon Arrays.sort(stus) , urutkan array siswa. Tidak peduli algoritma yang baik yang digunakan untuk mengimplementasikannya, pasti perlu membandingkan operasi "ukuran" dari dua objek. Jadi bagaimana Anda membandingkan "ukuran" dari dua objek? Antarmuka yang sebanding yang diimplementasikan oleh siswa berperan. Metode sortir akan melemparkan objek untuk dibandingkan dengan sebanding dan memanggil metode compareto untuk menilai "ukuran" dari dua objek ini berdasarkan nilai pengembaliannya. Oleh karena itu, dalam contoh ini, array siswa asli di luar orde yang diurutkan menjadi array siswa diurutkan berdasarkan nomor siswa.
Tetapi kami memperhatikan bahwa algoritma penyortiran terikat pada kelas siswa, dan siswa hanya memiliki satu algoritma penyortiran. Tapi ini tidak terjadi dalam masyarakat nyata. Bagaimana jika kita tidak ingin menyortir berdasarkan nomor siswa? Bagaimana jika kita ingin mengurutkan siswa berdasarkan nama? Kami hanya dapat memodifikasi metode compareTo dari antarmuka yang sebanding dari kelas siswa dan mengubahnya untuk mengurutkan berdasarkan nama. Bagaimana jika ada dua operasi dalam sistem yang sama, satu diurutkan berdasarkan nomor siswa dan yang lainnya diurutkan berdasarkan nama? Tidak mungkin untuk menulis dua implementasi metode compareto di badan kelas siswa. Dari sudut pandang ini, sebanding memiliki keterbatasan. Untuk menebus kekurangan ini, JDK juga memberi kami metode penyortiran lain, yang merupakan penyortiran pembanding yang akan kita bicarakan di bawah ini.
2. Penyortiran Komparator: java.util.util
Saya sebutkan di atas bahwa alasan mengapa antarmuka penyortiran pembanding disediakan adalah bahwa kadang -kadang perlu untuk mengurutkan objek yang sama dengan berbagai cara, dan penyortiran alami yang sebanding ini tidak dapat diimplementasikan. Selain itu, salah satu keuntungan dari antarmuka pembanding adalah bahwa ia memisahkan algoritma penyortiran perbandingan dari kelas entitas tertentu.
Jika Anda melihat melalui API, Anda akan menemukan bahwa ada juga bentuk array sort(T[] a, Comparator<? super T> c) Metode ini menggunakan obat generik untuk menulis parameter metode ini, yang belum kami sebutkan. Kita dapat memahaminya sebagai formulir ini: sort(Object[] a, Comparator c) , yang berarti menyortir array objek sesuai dengan algoritma penyortiran perbandingan yang diberikan oleh pembanding c. Ada dua metode yang didefinisikan dalam antarmuka pembanding: compare(Object o1, Object o2) dan equals metode. Karena metode equals memiliki metode untuk semua objek, ketika kami mengimplementasikan antarmuka pembanding, kami hanya perlu mengganti metode compare , alih -alih mengganti metode equals . Deskripsi metode overriding equals dalam antarmuka pembanding adalah: "Perhatikan bahwa selalu aman untuk tidak menimpa Object.equals(Object) . Namun, dalam beberapa kasus, menimpa metode ini dapat memungkinkan program untuk menentukan apakah dua pembanding yang berbeda memaksa penyortiran yang sama, sehingga meningkatkan kinerja." Kita hanya perlu mengetahui kalimat pertama dan tidak apa -apa. Dengan kata lain, kami tidak perlu memikirkan cara mengimplementasikan metode yang sama, karena bahkan jika kami tidak menunjukkan implementasi metode yang sama, tetapi menggunakan metode Equals dari kelas objek, kode tersebut masih aman.
Jadi mari kita tulis kode untuk mengurutkannya dengan pembanding. Ini masih dilakukan dengan kelas siswa, tetapi antarmuka yang sebanding tidak diimplementasikan. Karena kelas implementasi pembanding hanya menggunakan tampilan untuk mengimplementasikan satu metode, kita tidak perlu menulis kelas untuk mengimplementasikannya. Ketika kita perlu menggunakan pembanding, kita dapat menulis kelas internal anonim untuk mengimplementasikan pembanding.
Berikut adalah metode penyortiran dengan nama:
public void sortByName () {Siswa Stu1 = Siswa Baru (1, "Little"); Siswa Stu2 = Siswa Baru (2, "Cyntin"); Siswa Stu3 = Siswa Baru (3, "Tony"); Siswa Stu4 = Siswa Baru (4, "Gemini"); Siswa [] stus = siswa baru [4]; Stu0] = Stu1; Stu1; Stu4; Stu2] = Stu3; Stu3] = Stu2; System.out.println ("Array:" + Arrays.tostring (STUS)); Arrays.sort(stus, new Comparator() { @Override public int compare(Object o1, Object o2) { if (o1 instanceof Student && o2 instanceof Student) { Student s1 = (Student) o1; Student s2 = (Student) o2; //return s1.getId() - s2.getId(); //arrange by Id return s1.getName().compareTo(s2.getName()); // atur dengan nama} return 0;}}); System.out.println ("diurutkan:" + arrays.tostring (stus)); }Ketika kita perlu mengurutkan siswa berdasarkan nomor siswa, kita hanya perlu memodifikasi kode di kelas dalam yang mengimplementasikan pembanding dalam metode penyortiran kami, tanpa memodifikasi kelas siswa.
Catatan: Tentu saja, Anda juga dapat menggunakan kelas siswa untuk mengimplementasikan antarmuka pembanding, sehingga siswa adalah (adalah a) pembanding (pembanding). Ketika Anda perlu menggunakan jenis ini, cukup gunakan siswa sebagai pembanding. Anda dapat meneruskan siswa sebagai parameter ke dalam metode sortir karena siswa adalah pembanding. Tetapi kode seperti itu bukan kode yang sangat baik, karena salah satu alasan penting mengapa kami menggunakan pembanding adalah bahwa ia dapat memisahkan algoritma perbandingan dari kelas tertentu dan mengurangi kopling antar kelas.
TreeSet memberikan dukungan untuk kedua metode perbandingan, sesuai dengan dua metode konstruktor TreeSet:
1. Treeeset (): Perbandingan dan Urutkan Menurut metode Compareto dari antarmuka yang sebanding yang diimplementasikan oleh elemen di Treeset
2. Treeset (pembanding pembanding): Perbandingan dan Sortir Elemen di TreeSet Menurut pembanding pembanding yang diberikan
Saat menambahkan elemen ke treeset, TreeSet mengurutkan elemen. Adapun apakah akan menyortir dengan urutan atau pembanding alami, itu tergantung pada bagaimana konstruksi TreeSet Anda ditulis. Tentu saja, tidak akan ada perbandingan saat menambahkan elemen pertama. Tidak ada elemen di Treeset. Dengan siapa saya bisa membandingkannya?
Di bawah ini, kode uji TreeSet menggunakan dua metode penyortiran dan perbandingan diberikan:
/ *** Gunakan Sortir Natural* Siswa harus mengimplementasikan antarmuka yang sebanding, jika tidak ClassCastException akan dilemparkan*/ public void testsortedset3 () {student Stu1 = siswa baru (1, "sedikit"); Siswa Stu2 = Siswa Baru (2, "Cyntin"); Siswa Stu3 = Siswa Baru (3, "Tony"); Siswa Stu4 = Siswa Baru (4, "Gemini"); SortedSet set = TreeSet baru (); set.add (Stu1); set.add (Stu3); // Jika siswa tidak mengimplementasikan antarmuka yang sebanding, Throw ClassCastException Set.Add (Stu4); set.add (Stu2); set.add (Stu4); set.add (siswa baru (12, "kecil")); System.out.println (set); } / *** Gunakan pembanding untuk mengurutkan* Siswa dapat menjadi kelas Java sederhana tanpa mengimplementasikan antarmuka yang sebanding*/ public void testsortedset3 () {student Stu1 = siswa baru (1, "kecil"); Siswa Stu2 = Siswa Baru (2, "Cyntin"); Siswa Stu3 = Siswa Baru (3, "Tony"); Siswa Stu4 = Siswa Baru (4, "Gemini"); SortedSet set = TreeSet baru (pembanding baru () {@Override Public int Compare (Object O1, Object O2) {if (o1 instance dari siswa && o2 instance dari siswa) {student s1 = (siswa) o1; siswa s2 = (siswa) o2; return s1.getname ().}}}}}}}}} {O.). set.add (Stu1); set.add (Stu3); set.add (Stu4); set.add (Stu2); set.add (Stu4); set.add (siswa baru (12, "kecil")); System.out.println (set); } Selain itu, perkenalkan kelas alat, java.util.Collections . Perhatikan bahwa ini bukan antarmuka koleksi. Koleksi sangat mirip dengan kelas array. Array menyediakan serangkaian metode statis untuk operasi array, menemukan penyortiran, dan banyak lagi. Koleksi juga menyediakan serangkaian metode seperti itu, tetapi digunakan untuk memproses koleksi. Meskipun kelas koleksi sangat mirip dengan antarmuka koleksi, jangan tertipu dengan nama koleksi. Ini bukan kelas implementasi yang hanya dapat menangani antarmuka koleksi dan sub-antarmuka, tetapi juga dapat menangani kelas implementasi antarmuka peta.
Meringkaskan
Ini adalah akhir dari pengantar penyortiran alami dan penyortiran pembanding di Java. Artikel ini masih relatif detail. Saya harap ini dapat membantu Anda dalam belajar atau bekerja. Jika Anda memiliki pertanyaan, Anda dapat meninggalkan pesan untuk berkomunikasi.