Pembanding, menyusun koleksi - 1

"Hai, Amigo!"

"Hai, Bilaabo!"

"Hari ini kita akan mengkaji topik yang kecil, tetapi menarik dan berguna: menyusun koleksi."

"Mengisih? Saya pernah mendengar sesuatu tentang itu."

"Dulu, setiap pengaturcara harus dapat menulis algoritma pengisihan. Dapat dan terpaksa menulisnya. Tetapi hari-hari itu sudah berakhir. Hari ini, menulis kod pengisihan anda sendiri dianggap sebagai bentuk yang tidak baik, sama seperti menulis semula apa-apa lagi yang telah pun telah dicipta."

"Dalam Java (dan bahasa pengaturcaraan lain), pengisihan sudah dilaksanakan.  Tugas anda adalah untuk mempelajari cara menggunakan apa yang sudah ada dengan betul. "

"OKEY."

" Kelas pembantu Koleksi mempunyai kaedah isihan statik yang digunakan untuk mengisih koleksi—atau lebih tepat lagi, senarai. Elemen dalam Peta dan Set tidak mempunyai pesanan/indeks, jadi tiada apa-apa untuk diisih."

"Ya, saya ingat. Saya menggunakan kaedah ini sekali untuk mengisih senarai nombor."

"Hebat. Tetapi kaedah ini jauh lebih berkuasa daripada yang kelihatan pada pandangan pertama. Ia boleh mengisih bukan sahaja nombor, tetapi juga sebarang objek, berdasarkan mana-mana kriteria. Dua antara muka membantu kaedah melakukan ini: Sebanding dan Pembanding . "

"Kadangkala anda perlu mengisih objek, bukan nombor. Contohnya, katakan anda mempunyai senarai orang dan anda ingin mengisih mereka mengikut umur. Kami mempunyai antara muka Setanding untuk ini."

"Biar saya tunjukkan contoh kepada anda dahulu, dan kemudian semuanya akan menjadi lebih jelas:"

Contoh
public class Woman implements Comparable<Woman>
{
public int age;

public Woman(int age) {
this.age = age;
}

public int compareTo(Woman o)
{
return this.age - o.age;
}
}
Contoh bagaimana ia boleh digunakan:
public static void main(String[] args )
{
ArrayList<Woman> women = new ArrayList<Woman>();
women.add(new Woman(18));
women.add(new Woman(21));
women.add(new Woman(5));

Collections.sort(women);
}

"Untuk mengisih objek, anda mesti terlebih dahulu tahu cara membandingkannya. Untuk ini, kami menggunakan Comparable. Antara muka Comparable ialah generik, yang bermaksud ia menerima hujah jenis. Ia hanya mempunyai satu kaedah generik: compareTo(T o). Kaedah ini membandingkan objek semasa (ini) dan objek yang diluluskan sebagai hujah (o). Dalam erti kata lain, kita perlu melaksanakan kaedah ini dalam kelas kita dan kemudian menggunakannya untuk membandingkan objek semasa (ini) dengan objek yang diluluskan. "

"Dan bagaimana compareTo berfungsi? Saya menjangkakan ia akan kembali benar atau salah bergantung pada sama ada objek yang dilalui lebih besar atau lebih kecil."

"Perkara lebih rumit di sini. Kaedah compareTo tidak mengembalikan benar/salah. Sebaliknya, ia mengembalikan int. Ini sebenarnya dilakukan untuk kesederhanaan.

"Apabila komputer perlu menentukan sama ada satu nombor lebih besar daripada yang lain, ia hanya menolak nombor kedua daripada nombor pertama dan kemudian melihat hasilnya. Jika hasilnya 0, maka nombor adalah sama. Jika hasilnya kurang daripada sifar , maka nombor kedua lebih besar. Dan jika hasilnya lebih besar daripada sifar, maka nombor pertama lebih besar."

"Logik yang sama berlaku di sini. Mengikut spesifikasi, kaedah compareTo mesti mengembalikan sifar jika objek yang dibandingkan adalah sama. Jika kaedah compareTo mengembalikan nombor yang lebih besar daripada sifar, maka objek kita adalah lebih besar daripada objek yang diluluskan. "Jika compareTo kaedah mengembalikan nombor kurang daripada sifar, maka 'ini' adalah kurang daripada objek yang dilalui."

"Itu pelik sikit."

"Ya, tetapi jika anda membandingkan objek hanya berdasarkan beberapa sifat angka, maka anda hanya boleh mengembalikan perbezaan antara mereka dengan menolak satu daripada yang lain. Sama seperti ia dilakukan dalam contoh di atas."

public int compareTo(Woman o)
{
return this.age - o.age;
}

"Saya rasa saya faham segala-galanya. Tetapi mungkin tidak. Tetapi hampir semuanya."

"Bagus. Sekarang mari kita pertimbangkan masalah yang lebih praktikal. Katakan anda telah menulis tapak web yang hebat untuk membuat pakaian wanita di China. Anda menggunakan kelas Wanita untuk menerangkan pelanggan anda. Anda juga membuat halaman web dengan jadual di mana anda boleh melihat mereka semua . Tetapi ada masalah…"

"Objek Wanita anda mengandungi bukan sahaja umur, tetapi juga sekumpulan data lain: nama pertama, nama keluarga, tinggi, berat, bilangan kanak-kanak, dll."

"Jadual pengguna mempunyai banyak lajur, dan inilah soalannya: bagaimana anda mengisih pengguna anda mengikut pelbagai kriteria? Mengikut berat, mengikut umur, mengikut nama keluarga?"

"Hmm. Ya, saya sering melihat jadual yang membenarkan anda mengisih mengikut lajur. Jadi, bagaimana anda melakukannya?"

"Untuk ini, kami mempunyai antara muka kedua yang saya ingin beritahu anda tentang hari ini: antara muka Comparator. Ia juga mempunyai kaedah bandingkan, tetapi ia memerlukan dua hujah, bukan satu: int compare(T o1, T o2). Begini caranya berfungsi:"

Contoh
public class Woman
{
public int age;
public int childrenCount;
public int weight;
public int height;
public String name;

public Woman(int age) {
this.age = age;
}
}
Contoh bagaimana ia boleh digunakan:
public static void main(String[] args )
{
ArrayList<Woman> women = new ArrayList<Woman>();
women.add(new Woman(18));
women.add(new Woman(21));
women.add(new Woman(5));

Comparator<Woman> compareByHeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.height - o2.height;
}
};

Collections.sort(women, compareByHeight);
}

"Antara muka Comparator tidak menyembunyikan logik perbandingan objek di dalam kelas objek yang dibandingkan. Sebaliknya, ia dilaksanakan dalam kelas yang berasingan."

"Jadi, saya boleh membuat beberapa kelas yang melaksanakan antara muka Pembanding, dan minta setiap daripada mereka membandingkan sifat yang berbeza? Berat dalam satu, umur dalam satu lagi dan ketinggian dalam satu pertiga?"

"Ya, ia sangat mudah dan mudah."

"Kami hanya memanggil kaedah Collections.sort , menghantar senarai objek dan objek khas lain sebagai hujah kedua, yang melaksanakan antara muka Comparator dan memberitahu anda cara membandingkan pasangan objek dengan betul dalam proses pengisihan."

"Hmm. Saya rasa saya faham segala-galanya. Biar saya mencubanya. Katakan saya perlu mengisih pengguna mengikut berat. Ia akan menjadi seperti ini:"

Contoh pengisihan pengguna mengikut berat:
Comparator<Woman> compareByWeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.weight - o2.weight;
}
};

Collections.sort(women, compareByWeight);

"Ya, betul-betul."

"Hebat. Tetapi bagaimana jika saya mahu menyusun mengikut urutan terbalik?"

"Fikirkanlah. Jawapannya sangat mudah!"

"Saya faham! Seperti ini:"

Mengisih dalam tertib menaik:
return o1.weight - o2.weight;
Menyusun mengikut urutan menurun:
return o2.weight – o1.weight;

"Betul. Syabas."

"Dan jika saya mahu mengisih mengikut nama keluarga? Bagaimana saya boleh mengisih rentetan, Bilaabo?"

"Kelas String sudah melaksanakan kaedah compareTo. Anda hanya perlu memanggilnya:"

Contoh pengisihan pengguna mengikut nama:
Comparator<Woman> compareByName = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.name.compareTo(o2.name);
}
};

Collections.sort(women, compareByName);

"Itu adalah pengajaran yang hebat, Bilaabo. Terima kasih banyak-banyak."

"Dan terima kasih kepada awak, kawan saya!"